Split the program.[ch] files into several new files.
authorBrian <brian@yutani.localnet.net>
Thu, 14 Dec 2006 22:01:06 +0000 (15:01 -0700)
committerBrian <brian@yutani.localnet.net>
Thu, 14 Dec 2006 22:01:06 +0000 (15:01 -0700)
src/mesa/shader/prog_instruction.c [new file with mode: 0644]
src/mesa/shader/prog_instruction.h [new file with mode: 0644]
src/mesa/shader/prog_parameter.c [new file with mode: 0644]
src/mesa/shader/prog_parameter.h [new file with mode: 0644]
src/mesa/shader/prog_print.c [new file with mode: 0644]
src/mesa/shader/prog_print.h [new file with mode: 0644]
src/mesa/shader/prog_statevars.c [new file with mode: 0644]
src/mesa/shader/prog_statevars.h [new file with mode: 0644]

diff --git a/src/mesa/shader/prog_instruction.c b/src/mesa/shader/prog_instruction.c
new file mode 100644 (file)
index 0000000..f4dae76
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5.3
+ *
+ * Copyright (C) 1999-2005  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"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#include "glheader.h"
+#include "imports.h"
+#include "mtypes.h"
+#include "prog_instruction.h"
+
+
+/**
+ * Initialize program instruction fields to defaults.
+ * \param inst  first instruction to initialize
+ * \param count  number of instructions to initialize
+ */
+void
+_mesa_init_instructions(struct prog_instruction *inst, GLuint count)
+{
+   GLuint i;
+
+   _mesa_bzero(inst, count * sizeof(struct prog_instruction));
+
+   for (i = 0; i < count; i++) {
+      inst[i].SrcReg[0].File = PROGRAM_UNDEFINED;
+      inst[i].SrcReg[0].Swizzle = SWIZZLE_NOOP;
+      inst[i].SrcReg[1].File = PROGRAM_UNDEFINED;
+      inst[i].SrcReg[1].Swizzle = SWIZZLE_NOOP;
+      inst[i].SrcReg[2].File = PROGRAM_UNDEFINED;
+      inst[i].SrcReg[2].Swizzle = SWIZZLE_NOOP;
+
+      inst[i].DstReg.File = PROGRAM_UNDEFINED;
+      inst[i].DstReg.WriteMask = WRITEMASK_XYZW;
+      inst[i].DstReg.CondMask = COND_TR;
+      inst[i].DstReg.CondSwizzle = SWIZZLE_NOOP;
+
+      inst[i].SaturateMode = SATURATE_OFF;
+      inst[i].Precision = FLOAT32;
+   }
+}
+
+
+/**
+ * Allocate an array of program instructions.
+ * \param numInst  number of instructions
+ * \return pointer to instruction memory
+ */
+struct prog_instruction *
+_mesa_alloc_instructions(GLuint numInst)
+{
+   return (struct prog_instruction *)
+      _mesa_calloc(numInst * sizeof(struct prog_instruction));
+}
+
+
+/**
+ * Reallocate memory storing an array of program instructions.
+ * This is used when we need to append additional instructions onto an
+ * program.
+ * \param oldInst  pointer to first of old/src instructions
+ * \param numOldInst  number of instructions at <oldInst>
+ * \param numNewInst  desired size of new instruction array.
+ * \return  pointer to start of new instruction array.
+ */
+struct prog_instruction *
+_mesa_realloc_instructions(struct prog_instruction *oldInst,
+                           GLuint numOldInst, GLuint numNewInst)
+{
+   struct prog_instruction *newInst;
+
+   newInst = (struct prog_instruction *)
+      _mesa_realloc(oldInst,
+                    numOldInst * sizeof(struct prog_instruction),
+                    numNewInst * sizeof(struct prog_instruction));
+
+   return newInst;
+}
+
+
diff --git a/src/mesa/shader/prog_instruction.h b/src/mesa/shader/prog_instruction.h
new file mode 100644 (file)
index 0000000..bda6a2c
--- /dev/null
@@ -0,0 +1,403 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5
+ *
+ * Copyright (C) 1999-2005  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"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+/**
+ * \file prog_instruction.h
+ *
+ * Private vertex program types and constants only used by files
+ * related to vertex programs.
+ *
+ * \author Brian Paul
+ * \author Keith Whitwell
+ * \author Ian Romanick <idr@us.ibm.com>
+ */
+
+
+#ifndef PROG_INSTRUCTION_H
+#define PROG_INSTRUCTION_H
+
+
+/* for GL_ARB_v_p and GL_ARB_f_p SWZ instruction */
+#define SWIZZLE_X    0
+#define SWIZZLE_Y    1
+#define SWIZZLE_Z    2
+#define SWIZZLE_W    3
+#define SWIZZLE_ZERO 4         /* keep these values together: KW */
+#define SWIZZLE_ONE  5         /* keep these values together: KW */
+
+#define MAKE_SWIZZLE4(a,b,c,d) (((a)<<0) | ((b)<<3) | ((c)<<6) | ((d)<<9))
+#define SWIZZLE_NOOP           MAKE_SWIZZLE4(0,1,2,3)
+#define GET_SWZ(swz, idx)      (((swz) >> ((idx)*3)) & 0x7)
+#define GET_BIT(msk, idx)      (((msk) >> (idx)) & 0x1)
+
+
+#define WRITEMASK_X     0x1
+#define WRITEMASK_Y     0x2
+#define WRITEMASK_XY    0x3
+#define WRITEMASK_Z     0x4
+#define WRITEMASK_XZ    0x5
+#define WRITEMASK_YZ    0x6
+#define WRITEMASK_XYZ   0x7
+#define WRITEMASK_W     0x8
+#define WRITEMASK_XW    0x9
+#define WRITEMASK_YW    0xa
+#define WRITEMASK_XYW   0xb
+#define WRITEMASK_ZW    0xc
+#define WRITEMASK_XZW   0xd
+#define WRITEMASK_YZW   0xe
+#define WRITEMASK_XYZW  0xf
+
+
+/**
+ * Condition codes for GL_NV_fragment_program
+ */
+/*@{*/
+#define COND_GT  1  /* greater than zero */
+#define COND_EQ  2  /* equal to zero */
+#define COND_LT  3  /* less than zero */
+#define COND_UN  4  /* unordered (NaN) */
+#define COND_GE  5  /* greater then or equal to zero */
+#define COND_LE  6  /* less then or equal to zero */
+#define COND_NE  7  /* not equal to zero */
+#define COND_TR  8  /* always true */
+#define COND_FL  9  /* always false */
+/*@}*/
+
+
+/**
+ * Instruction precision for GL_NV_fragment_program
+ */
+/*@{*/
+#define FLOAT32  0x1
+#define FLOAT16  0x2
+#define FIXED12  0x4
+/*@}*/
+
+
+/**
+ * Saturation modes when storing values.
+ */
+/*@{*/
+#define SATURATE_OFF            0
+#define SATURATE_ZERO_ONE       1
+#define SATURATE_PLUS_MINUS_ONE 2
+/*@}*/
+
+
+/**
+ * Per-component negation masks
+ */
+/*@{*/
+#define NEGATE_X    0x1
+#define NEGATE_Y    0x2
+#define NEGATE_Z    0x4
+#define NEGATE_W    0x8
+#define NEGATE_XYZW 0xf
+#define NEGATE_NONE 0x0
+/*@}*/
+
+
+/**
+ * Program instruction opcodes, for both vertex and fragment programs.
+ * \note changes to this opcode list must be reflected in t_vb_arbprogram.c
+ */
+typedef enum prog_opcode {
+                     /* ARB_vp   ARB_fp   NV_vp   NV_fp */
+                     /*---------------------------------*/
+   OPCODE_NOP = 0,
+   OPCODE_ABS,       /*   X        X       1.1          */
+   OPCODE_ADD,       /*   X        X       X       X    */
+   OPCODE_ARA,       /*                    2            */
+   OPCODE_ARL,       /*   X                X            */
+   OPCODE_ARL_NV,    /*                    2            */
+   OPCODE_ARR,       /*                    2            */
+   OPCODE_BRA,       /*                    2            */
+   OPCODE_CAL,       /*                    2       2    */
+   OPCODE_CMP,       /*            X                    */
+   OPCODE_COS,       /*            X       2       X    */
+   OPCODE_DDX,       /*                            X    */
+   OPCODE_DDY,       /*                            X    */
+   OPCODE_DP3,       /*   X        X       X       X    */
+   OPCODE_DP4,       /*   X        X       X       X    */
+   OPCODE_DPH,       /*   X        X       1.1          */
+   OPCODE_DST,       /*   X        X       X       X    */
+   OPCODE_END,       /*   X        X       X       X    */
+   OPCODE_EX2,       /*   X        X       2       X    */
+   OPCODE_EXP,       /*   X                X            */
+   OPCODE_FLR,       /*   X        X       2       X    */
+   OPCODE_FRC,       /*   X        X       2       X    */
+   OPCODE_KIL,       /*            X                    */
+   OPCODE_KIL_NV,    /*                            X    */
+   OPCODE_LG2,       /*   X        X       2       X    */
+   OPCODE_LIT,       /*   X        X       X       X    */
+   OPCODE_LOG,       /*   X                X            */
+   OPCODE_LRP,       /*            X               X    */
+   OPCODE_MAD,       /*   X        X       X       X    */
+   OPCODE_MAX,       /*   X        X       X       X    */
+   OPCODE_MIN,       /*   X        X       X       X    */
+   OPCODE_MOV,       /*   X        X       X       X    */
+   OPCODE_MUL,       /*   X        X       X       X    */
+   OPCODE_PK2H,      /*                            X    */
+   OPCODE_PK2US,     /*                            X    */
+   OPCODE_PK4B,      /*                            X    */
+   OPCODE_PK4UB,     /*                            X    */
+   OPCODE_POW,       /*   X        X               X    */
+   OPCODE_POPA,      /*                    3            */
+   OPCODE_PRINT,     /*                    X       X    */
+   OPCODE_PUSHA,     /*                    3            */
+   OPCODE_RCC,       /*                    1.1          */
+   OPCODE_RCP,       /*   X        X       X       X    */
+   OPCODE_RET,       /*                    2       2    */
+   OPCODE_RFL,       /*            X               X    */
+   OPCODE_RSQ,       /*   X        X       X       X    */
+   OPCODE_SCS,       /*            X                    */
+   OPCODE_SEQ,       /*                    2       X    */
+   OPCODE_SFL,       /*                    2       X    */
+   OPCODE_SGE,       /*   X        X       X       X    */
+   OPCODE_SGT,       /*                    2       X    */
+   OPCODE_SIN,       /*            X       2       X    */
+   OPCODE_SLE,       /*                    2       X    */
+   OPCODE_SLT,       /*   X        X       X       X    */
+   OPCODE_SNE,       /*                    2       X    */
+   OPCODE_SSG,       /*                    2            */
+   OPCODE_STR,       /*                    2       X    */
+   OPCODE_SUB,       /*   X        X       1.1     X    */
+   OPCODE_SWZ,       /*   X        X                    */
+   OPCODE_TEX,       /*            X       3       X    */
+   OPCODE_TXB,       /*            X       3            */
+   OPCODE_TXD,       /*                            X    */
+   OPCODE_TXL,       /*                    3       2    */
+   OPCODE_TXP,       /*            X                    */
+   OPCODE_TXP_NV,    /*                    3       X    */
+   OPCODE_UP2H,      /*                            X    */
+   OPCODE_UP2US,     /*                            X    */
+   OPCODE_UP4B,      /*                            X    */
+   OPCODE_UP4UB,     /*                            X    */
+   OPCODE_X2D,       /*                            X    */
+   OPCODE_XPD,       /*   X        X                    */
+   MAX_OPCODE
+} gl_inst_opcode;
+
+
+/**
+ * Instruction source register.
+ */
+struct prog_src_register
+{
+   GLuint File:4;      /**< One of the PROGRAM_* register file values. */
+   GLint Index:9;      /**< May be negative for relative addressing. */
+   GLuint Swizzle:12;
+   GLuint RelAddr:1;
+
+   /**
+    * \name Source register "sign" control.
+    *
+    * The ARB and NV extensions allow varrying degrees of control over the
+    * sign of the source vector components.  These values allow enough control
+    * for all flavors of the extensions.
+    */
+   /*@{*/
+   /**
+    * Per-component negation for the SWZ instruction.  For non-SWZ
+    * instructions the only possible values are NEGATE_XYZW and NEGATE_NONE.
+    *
+    * \since
+    * ARB_vertex_program, ARB_fragment_program
+    */
+   GLuint NegateBase:4;
+
+   /**
+    * Take the component-wise absolute value.
+    *
+    * \since
+    * NV_fragment_program, NV_fragment_program_option, NV_vertex_program2,
+    * NV_vertex_program2_option.
+    */
+   GLuint Abs:1;
+
+   /**
+    * Post-absolute value negation (all components).
+    */
+   GLuint NegateAbs:1;
+   /*@}*/
+};
+
+
+/**
+ * Instruction destination register.
+ */
+struct prog_dst_register
+{
+   /**
+    * One of the PROGRAM_* register file values.
+    */
+   GLuint File:4;
+
+   GLuint Index:8;
+   GLuint WriteMask:4;
+
+   /**
+    * \name Conditional destination update control.
+    *
+    * \since
+    * NV_fragment_program, NV_fragment_program_option, NV_vertex_program2,
+    * NV_vertex_program2_option.
+    */
+   /*@{*/
+   /**
+    * Takes one of the 9 possible condition values (EQ, FL, GT, GE, LE, LT,
+    * NE, TR, or UN).  Destination update is enabled if the matching
+    * (swizzled) condition code value passes.  When a conditional update mask
+    * is not specified, this will be \c COND_TR.
+    */
+   GLuint CondMask:4;
+
+   /**
+    * Condition code swizzle value.
+    */
+   GLuint CondSwizzle:12;
+   
+   /**
+    * Selects the condition code register to use for conditional destination
+    * update masking.  In NV_fragmnet_program or NV_vertex_program2 mode, only
+    * condition code register 0 is available.  In NV_vertex_program3 mode, 
+    * condition code registers 0 and 1 are available.
+    */
+   GLuint CondSrc:1;
+   /*@}*/
+
+   GLuint pad:31;
+};
+
+
+/**
+ * Vertex/fragment program instruction.
+ */
+struct prog_instruction
+{
+   gl_inst_opcode Opcode;
+#if FEATURE_MESA_program_debug
+   GLshort StringPos;
+#endif
+   /**
+    * Arbitrary data.  Used for the PRINT, CAL, and BRA instructions.
+    */
+   void *Data;
+
+   struct prog_src_register SrcReg[3];
+   struct prog_dst_register DstReg;
+
+   /**
+    * Indicates that the instruction should update the condition code
+    * register.
+    *
+    * \since
+    * NV_fragment_program, NV_fragment_program_option, NV_vertex_program2,
+    * NV_vertex_program2_option.
+    */
+   GLuint CondUpdate:1;
+
+   /**
+    * If prog_instruction::CondUpdate is \c GL_TRUE, this value selects the
+    * condition code register that is to be updated.
+    *
+    * In GL_NV_fragment_program or GL_NV_vertex_program2 mode, only condition
+    * code register 0 is available.  In GL_NV_vertex_program3 mode, condition
+    * code registers 0 and 1 are available.
+    *
+    * \since
+    * NV_fragment_program, NV_fragment_program_option, NV_vertex_program2,
+    * NV_vertex_program2_option.
+    */
+   GLuint CondDst:1;
+
+   /**
+    * Saturate each value of the vectored result to the range [0,1] or the
+    * range [-1,1].  \c SSAT mode (i.e., saturation to the range [-1,1]) is
+    * only available in NV_fragment_program2 mode.
+    * Value is one of the SATURATE_* tokens.
+    *
+    * \since
+    * NV_fragment_program, NV_fragment_program_option, NV_vertex_program3.
+    */
+   GLuint SaturateMode:2;
+   
+   /**
+    * Per-instruction selectable precision.
+    *
+    * \since
+    * NV_fragment_program, NV_fragment_program_option.
+    */
+   GLuint Precision:3;
+
+   /**
+    * \name Texture source controls.
+    * 
+    * The texture source controls are only used with the \c TEX, \c TXD,
+    * \c TXL, and \c TXP instructions.
+    *
+    * \since
+    * ARB_fragment_program, NV_fragment_program, NV_vertex_program3.
+    */
+   /*@{*/
+   /**
+    * Source texture unit.  OpenGL supports a maximum of 32 texture
+    * units.
+    */
+   GLuint TexSrcUnit:5;
+   
+   /**
+    * Source texture target, one of TEXTURE_{1D,2D,3D,CUBE,RECT}_INDEX.
+    */
+   GLuint TexSrcTarget:3;
+   /*@}*/
+
+   /**
+    * For BRA and CAL instructions, the location to jump to.
+    */
+   GLuint BranchTarget;
+
+   const char *Comment;
+};
+
+
+extern void
+_mesa_init_instructions(struct prog_instruction *inst, GLuint count);
+
+extern struct prog_instruction *
+_mesa_alloc_instructions(GLuint numInst);
+
+extern struct prog_instruction *
+_mesa_realloc_instructions(struct prog_instruction *oldInst,
+                           GLuint numOldInst, GLuint numNewInst);
+
+extern GLuint
+_mesa_num_inst_src_regs(gl_inst_opcode opcode);
+
+extern const char *
+_mesa_opcode_string(gl_inst_opcode opcode);
+
+
+#endif /* PROG_INSTRUCTION_H */
diff --git a/src/mesa/shader/prog_parameter.c b/src/mesa/shader/prog_parameter.c
new file mode 100644 (file)
index 0000000..f634e38
--- /dev/null
@@ -0,0 +1,448 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5.2
+ *
+ * Copyright (C) 1999-2006  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"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file prog_parameter.c
+ * Program parameter lists and functions.
+ * \author Brian Paul
+ */
+
+
+#include "glheader.h"
+#include "imports.h"
+#include "macros.h"
+#include "mtypes.h"
+#include "program.h"
+#include "prog_instruction.h"
+#include "prog_parameter.h"
+#include "prog_statevars.h"
+
+
+struct gl_program_parameter_list *
+_mesa_new_parameter_list(void)
+{
+   return (struct gl_program_parameter_list *)
+      _mesa_calloc(sizeof(struct gl_program_parameter_list));
+}
+
+
+/**
+ * Free a parameter list and all its parameters
+ */
+void
+_mesa_free_parameter_list(struct gl_program_parameter_list *paramList)
+{
+   GLuint i;
+   for (i = 0; i < paramList->NumParameters; i++) {
+      if (paramList->Parameters[i].Name)
+        _mesa_free((void *) paramList->Parameters[i].Name);
+   }
+   _mesa_free(paramList->Parameters);
+   if (paramList->ParameterValues)
+      _mesa_align_free(paramList->ParameterValues);
+   _mesa_free(paramList);
+}
+
+
+
+/**
+ * Add a new parameter to a parameter list.
+ * \param paramList  the list to add the parameter to
+ * \param name  the parameter name, will be duplicated/copied!
+ * \param values  initial parameter value, up to 4 GLfloats
+ * \param size  number of elements in 'values' vector (1..4)
+ * \param type  type of parameter, such as 
+ * \return  index of new parameter in the list, or -1 if error (out of mem)
+ */
+GLint
+_mesa_add_parameter(struct gl_program_parameter_list *paramList,
+                    const char *name, const GLfloat values[4], GLuint size,
+                    enum register_file type)
+{
+   const GLuint n = paramList->NumParameters;
+
+   if (n == paramList->Size) {
+      /* Need to grow the parameter list array */
+      if (paramList->Size == 0)
+        paramList->Size = 8;
+      else
+         paramList->Size *= 2;
+
+      /* realloc arrays */
+      paramList->Parameters = (struct gl_program_parameter *)
+        _mesa_realloc(paramList->Parameters,
+                      n * sizeof(struct gl_program_parameter),
+                      paramList->Size * sizeof(struct gl_program_parameter));
+
+      paramList->ParameterValues = (GLfloat (*)[4])
+         _mesa_align_realloc(paramList->ParameterValues,         /* old buf */
+                             n * 4 * sizeof(GLfloat),            /* old size */
+                             paramList->Size * 4 *sizeof(GLfloat), /* new sz */
+                             16);
+   }
+
+   if (!paramList->Parameters ||
+       !paramList->ParameterValues) {
+      /* out of memory */
+      paramList->NumParameters = 0;
+      paramList->Size = 0;
+      return -1;
+   }
+   else {
+      paramList->NumParameters = n + 1;
+
+      _mesa_memset(&paramList->Parameters[n], 0, 
+                  sizeof(struct gl_program_parameter));
+
+      paramList->Parameters[n].Name = name ? _mesa_strdup(name) : NULL;
+      paramList->Parameters[n].Type = type;
+      paramList->Parameters[n].Size = size;
+      if (values)
+         COPY_4V(paramList->ParameterValues[n], values);
+      return (GLint) n;
+   }
+}
+
+
+/**
+ * Add a new named program parameter (Ex: NV_fragment_program DEFINE statement)
+ * \return index of the new entry in the parameter list
+ */
+GLint
+_mesa_add_named_parameter(struct gl_program_parameter_list *paramList,
+                          const char *name, const GLfloat values[4])
+{
+   return _mesa_add_parameter(paramList, name, values, 4, PROGRAM_NAMED_PARAM);
+}
+
+
+/**
+ * Add a new named constant to the parameter list.
+ * This will be used when the program contains something like this:
+ *    PARAM myVals = { 0, 1, 2, 3 };
+ *
+ * \param paramList  the parameter list
+ * \param name  the name for the constant
+ * \param values  four float values
+ * \return index/position of the new parameter in the parameter list
+ */
+GLint
+_mesa_add_named_constant(struct gl_program_parameter_list *paramList,
+                         const char *name, const GLfloat values[4],
+                         GLuint size)
+{
+#if 0 /* disable this for now -- we need to save the name! */
+   GLint pos;
+   GLuint swizzle;
+   ASSERT(size == 4); /* XXX future feature */
+   /* check if we already have this constant */
+   if (_mesa_lookup_parameter_constant(paramList, values, 4, &pos, &swizzle)) {
+      return pos;
+   }
+#endif
+   size = 4; /** XXX fix */
+   return _mesa_add_parameter(paramList, name, values, size, PROGRAM_CONSTANT);
+}
+
+
+/**
+ * Add a new unnamed constant to the parameter list.
+ * This will be used when the program contains something like this:
+ *    MOV r, { 0, 1, 2, 3 };
+ *
+ * \param paramList  the parameter list
+ * \param values  four float values
+ * \param swizzleOut  returns swizzle mask for accessing the constant
+ * \return index/position of the new parameter in the parameter list.
+ */
+GLint
+_mesa_add_unnamed_constant(struct gl_program_parameter_list *paramList,
+                           const GLfloat values[4], GLuint size,
+                           GLuint *swizzleOut)
+{
+   GLint pos;
+   GLuint swizzle;
+   ASSERT(size >= 1);
+   ASSERT(size <= 4);
+   size = 4; /* XXX temporary */
+   /* check if we already have this constant */
+   if (_mesa_lookup_parameter_constant(paramList, values,
+                                       size, &pos, &swizzle)) {
+      return pos;
+   }
+   return _mesa_add_parameter(paramList, NULL, values, size, PROGRAM_CONSTANT);
+}
+
+
+GLint
+_mesa_add_uniform(struct gl_program_parameter_list *paramList,
+                  const char *name, GLuint size)
+{
+   GLint i = _mesa_lookup_parameter_index(paramList, -1, name);
+   if (i >= 0 && paramList->Parameters[i].Type == PROGRAM_UNIFORM) {
+      /* already in list */
+      return i;
+   }
+   else {
+      assert(size == 4);
+      i = _mesa_add_parameter(paramList, name, NULL, size, PROGRAM_UNIFORM);
+      return i;
+   }
+}
+
+
+GLint
+_mesa_add_varying(struct gl_program_parameter_list *paramList,
+                  const char *name, GLuint size)
+{
+   GLint i = _mesa_lookup_parameter_index(paramList, -1, name);
+   if (i >= 0 && paramList->Parameters[i].Type == PROGRAM_VARYING) {
+      /* already in list */
+      return i;
+   }
+   else {
+      assert(size == 4);
+      i = _mesa_add_parameter(paramList, name, NULL, size, PROGRAM_VARYING);
+      return i;
+   }
+}
+
+
+
+
+#if 0 /* not used yet */
+/**
+ * Returns the number of 4-component registers needed to store a piece
+ * of GL state.  For matrices this may be as many as 4 registers,
+ * everything else needs
+ * just 1 register.
+ */
+static GLuint
+sizeof_state_reference(const GLint *stateTokens)
+{
+   if (stateTokens[0] == STATE_MATRIX) {
+      GLuint rows = stateTokens[4] - stateTokens[3] + 1;
+      assert(rows >= 1);
+      assert(rows <= 4);
+      return rows;
+   }
+   else {
+      return 1;
+   }
+}
+#endif
+
+
+/**
+ * Add a new state reference to the parameter list.
+ * This will be used when the program contains something like this:
+ *    PARAM ambient = state.material.front.ambient;
+ *
+ * \param paramList  the parameter list
+ * \param state  an array of 6 state tokens
+ * \return index of the new parameter.
+ */
+GLint
+_mesa_add_state_reference(struct gl_program_parameter_list *paramList,
+                          const GLint *stateTokens)
+{
+   const GLuint size = 4; /* XXX fix */
+   const char *name;
+   GLint index;
+
+   /* Check if the state reference is already in the list */
+   for (index = 0; index < paramList->NumParameters; index++) {
+      GLuint i, match = 0;
+      for (i = 0; i < 6; i++) {
+         if (paramList->Parameters[index].StateIndexes[i] == stateTokens[i]) {
+            match++;
+         }
+         else {
+            break;
+         }
+      }
+      if (match == 6) {
+         /* this state reference is already in the parameter list */
+         return index;
+      }
+   }
+
+   name = _mesa_program_state_string(stateTokens);
+   index = _mesa_add_parameter(paramList, name, NULL, size, PROGRAM_STATE_VAR);
+   if (index >= 0) {
+      GLuint i;
+      for (i = 0; i < 6; i++) {
+         paramList->Parameters[index].StateIndexes[i]
+            = (gl_state_index) stateTokens[i];
+      }
+      paramList->StateFlags |= _mesa_program_state_flags(stateTokens);
+   }
+
+   /* free name string here since we duplicated it in add_parameter() */
+   _mesa_free((void *) name);
+
+   return index;
+}
+
+
+/**
+ * Lookup a parameter value by name in the given parameter list.
+ * \return pointer to the float[4] values.
+ */
+GLfloat *
+_mesa_lookup_parameter_value(const struct gl_program_parameter_list *paramList,
+                             GLsizei nameLen, const char *name)
+{
+   GLuint i = _mesa_lookup_parameter_index(paramList, nameLen, name);
+   if (i < 0)
+      return NULL;
+   else
+      return paramList->ParameterValues[i];
+}
+
+
+/**
+ * Given a program parameter name, find its position in the list of parameters.
+ * \param paramList  the parameter list to search
+ * \param nameLen  length of name (in chars).
+ *                 If length is negative, assume that name is null-terminated.
+ * \param name  the name to search for
+ * \return index of parameter in the list.
+ */
+GLint
+_mesa_lookup_parameter_index(const struct gl_program_parameter_list *paramList,
+                             GLsizei nameLen, const char *name)
+{
+   GLint i;
+
+   if (!paramList)
+      return -1;
+
+   if (nameLen == -1) {
+      /* name is null-terminated */
+      for (i = 0; i < (GLint) paramList->NumParameters; i++) {
+         if (paramList->Parameters[i].Name &&
+            _mesa_strcmp(paramList->Parameters[i].Name, name) == 0)
+            return i;
+      }
+   }
+   else {
+      /* name is not null-terminated, use nameLen */
+      for (i = 0; i < (GLint) paramList->NumParameters; i++) {
+         if (paramList->Parameters[i].Name &&
+            _mesa_strncmp(paramList->Parameters[i].Name, name, nameLen) == 0
+             && _mesa_strlen(paramList->Parameters[i].Name) == (size_t)nameLen)
+            return i;
+      }
+   }
+   return -1;
+}
+
+
+/**
+ * Look for a float vector in the given parameter list.  The float vector
+ * may be of length 1, 2, 3 or 4.
+ * \param paramList  the parameter list to search
+ * \param v  the float vector to search for
+ * \param size  number of element in v
+ * \param posOut  returns the position of the constant, if found
+ * \param swizzleOut  returns a swizzle mask describing location of the
+ *                    vector elements if found
+ * \return GL_TRUE if found, GL_FALSE if not found
+ */
+GLboolean
+_mesa_lookup_parameter_constant(const struct gl_program_parameter_list *paramList,
+                                const GLfloat v[], GLsizei vSize,
+                                GLint *posOut, GLuint *swizzleOut)
+{
+   GLuint i;
+
+   assert(vSize >= 1);
+   assert(vSize <= 4);
+
+   if (!paramList)
+      return -1;
+
+   for (i = 0; i < paramList->NumParameters; i++) {
+      if (paramList->Parameters[i].Type == PROGRAM_CONSTANT) {
+         const GLint maxShift = 4 - vSize;
+         GLint shift, j;
+         for (shift = 0; shift <= maxShift; shift++) {
+            GLint matched = 0;
+            GLuint swizzle[4];
+            swizzle[0] = swizzle[1] = swizzle[2] = swizzle[3] = 0;
+            /* XXX we could do out-of-order swizzle matches too, someday */
+            for (j = 0; j < vSize; j++) {
+               assert(shift + j < 4);
+               if (paramList->ParameterValues[i][shift + j] == v[j]) {
+                  matched++;
+                  swizzle[j] = shift + j;
+                  ASSERT(swizzle[j] >= SWIZZLE_X);
+                  ASSERT(swizzle[j] <= SWIZZLE_W);
+               }
+            }
+            if (matched == vSize) {
+               /* found! */
+               *posOut = i;
+               *swizzleOut = MAKE_SWIZZLE4(swizzle[0], swizzle[1],
+                                           swizzle[2], swizzle[3]);
+               return GL_TRUE;
+            }
+         }
+      }
+   }
+
+   *posOut = -1;
+   return GL_FALSE;
+}
+
+
+struct gl_program_parameter_list *
+_mesa_clone_parameter_list(const struct gl_program_parameter_list *list)
+{
+   struct gl_program_parameter_list *clone;
+   GLuint i;
+
+   clone = _mesa_new_parameter_list();
+   if (!clone)
+      return NULL;
+
+   /** Not too efficient, but correct */
+   for (i = 0; i < list->NumParameters; i++) {
+      struct gl_program_parameter *p = list->Parameters + i;
+      GLint j = _mesa_add_parameter(clone, p->Name, list->ParameterValues[i],
+                                    p->Size, p->Type);
+      ASSERT(j >= 0);
+      /* copy state indexes */
+      if (p->Type == PROGRAM_STATE_VAR) {
+         GLint k;
+         struct gl_program_parameter *q = clone->Parameters + j;
+         for (k = 0; k < 6; k++) {
+            q->StateIndexes[k] = p->StateIndexes[k];
+         }
+      }
+   }
+
+   return clone;
+}
diff --git a/src/mesa/shader/prog_parameter.h b/src/mesa/shader/prog_parameter.h
new file mode 100644 (file)
index 0000000..c60ef54
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5.2
+ *
+ * Copyright (C) 1999-2006  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"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file prog_parameter.c
+ * Program parameter lists and functions.
+ * \author Brian Paul
+ */
+
+#ifndef PROG_PARAMETER_H
+#define PROG_PARAMETER_H
+
+#include "mtypes.h"
+
+
+/**
+ * Named program parameters 
+ * Used for NV_fragment_program "DEFINE"d constants and "DECLARE"d parameters,
+ * and ARB_fragment_program global state references.  For the later, Name
+ * might be "state.light[0].diffuse", for example.
+ */
+struct gl_program_parameter
+{
+   const char *Name;        /**< Null-terminated string */
+   enum register_file Type; /**< PROGRAM_NAMED_PARAM, CONSTANT or STATE_VAR */
+   GLuint Size;             /**< Number of components (1..4) */
+   /**
+    * A sequence of STATE_* tokens and integers to identify GL state.
+    */
+   GLuint StateIndexes[6];
+};
+
+
+/**
+ * A list of the above program_parameter instances.
+ */
+struct gl_program_parameter_list
+{
+   GLuint Size;           /**< allocated size of Parameters, ParameterValues */
+   GLuint NumParameters;  /**< number of parameters in arrays */
+   struct gl_program_parameter *Parameters; /**< Array [Size] */
+   GLfloat (*ParameterValues)[4];        /**< Array [Size] of GLfloat[4] */
+   GLbitfield StateFlags; /**< _NEW_* flags indicating which state changes
+                               might invalidate ParameterValues[] */
+};
+
+
+extern struct gl_program_parameter_list *
+_mesa_new_parameter_list(void);
+
+extern void
+_mesa_free_parameter_list(struct gl_program_parameter_list *paramList);
+
+extern struct gl_program_parameter_list *
+_mesa_clone_parameter_list(const struct gl_program_parameter_list *list);
+
+extern GLint
+_mesa_add_parameter(struct gl_program_parameter_list *paramList,
+                    const char *name, const GLfloat values[4], GLuint size,
+                    enum register_file type);
+
+extern GLint
+_mesa_add_named_parameter(struct gl_program_parameter_list *paramList,
+                          const char *name, const GLfloat values[4]);
+
+extern GLint
+_mesa_add_named_constant(struct gl_program_parameter_list *paramList,
+                         const char *name, const GLfloat values[4],
+                         GLuint size);
+
+extern GLint
+_mesa_add_unnamed_constant(struct gl_program_parameter_list *paramList,
+                           const GLfloat values[4], GLuint size,
+                           GLuint *swizzleOut);
+
+extern GLint
+_mesa_add_uniform(struct gl_program_parameter_list *paramList,
+                  const char *name, GLuint size);
+
+extern GLint
+_mesa_add_varying(struct gl_program_parameter_list *paramList,
+                  const char *name, GLuint size);
+
+extern GLint
+_mesa_add_state_reference(struct gl_program_parameter_list *paramList,
+                          const GLint *stateTokens);
+
+extern GLfloat *
+_mesa_lookup_parameter_value(const struct gl_program_parameter_list *paramList,
+                             GLsizei nameLen, const char *name);
+
+extern GLint
+_mesa_lookup_parameter_index(const struct gl_program_parameter_list *paramList,
+                             GLsizei nameLen, const char *name);
+
+extern GLboolean
+_mesa_lookup_parameter_constant(const struct gl_program_parameter_list *paramList,
+                                const GLfloat v[], GLsizei vSize,
+                                GLint *posOut, GLuint *swizzleOut);
+
+
+#endif /* PROG_PARAMETER_H */
diff --git a/src/mesa/shader/prog_print.c b/src/mesa/shader/prog_print.c
new file mode 100644 (file)
index 0000000..eded71b
--- /dev/null
@@ -0,0 +1,464 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5.3
+ *
+ * Copyright (C) 1999-2006  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"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file prog_print.c
+ * Print vertex/fragment programs - for debugging.
+ * \author Brian Paul
+ */
+
+#include "glheader.h"
+#include "context.h"
+#include "imports.h"
+#include "macros.h"
+#include "program.h"
+#include "prog_instruction.h"
+#include "prog_parameter.h"
+#include "prog_print.h"
+#include "prog_statevars.h"
+
+
+
+/**
+ * Basic info about each instruction
+ */
+struct instruction_info
+{
+   gl_inst_opcode Opcode;
+   const char *Name;
+   GLuint NumSrcRegs;
+};
+
+/**
+ * Instruction info
+ * \note Opcode should equal array index!
+ */
+static const struct instruction_info InstInfo[MAX_OPCODE] = {
+   { OPCODE_NOP,    "NOP",   0 },
+   { OPCODE_ABS,    "ABS",   1 },
+   { OPCODE_ADD,    "ADD",   2 },
+   { OPCODE_ARA,    "ARA",   1 },
+   { OPCODE_ARL,    "ARL",   1 },
+   { OPCODE_ARL_NV, "ARL",   1 },
+   { OPCODE_ARR,    "ARL",   1 },
+   { OPCODE_BRA,    "BRA",   0 },
+   { OPCODE_CAL,    "CAL",   0 },
+   { OPCODE_CMP,    "CMP",   3 },
+   { OPCODE_COS,    "COS",   1 },
+   { OPCODE_DDX,    "DDX",   1 },
+   { OPCODE_DDY,    "DDY",   1 },
+   { OPCODE_DP3,    "DP3",   2 },
+   { OPCODE_DP4,    "DP4",   2 },
+   { OPCODE_DPH,    "DPH",   2 },
+   { OPCODE_DST,    "DST",   2 },
+   { OPCODE_END,    "END",   0 },
+   { OPCODE_EX2,    "EX2",   1 },
+   { OPCODE_EXP,    "EXP",   1 },
+   { OPCODE_FLR,    "FLR",   1 },
+   { OPCODE_FRC,    "FRC",   1 },
+   { OPCODE_KIL,    "KIL",   1 },
+   { OPCODE_KIL_NV, "KIL",   0 },
+   { OPCODE_LG2,    "LG2",   1 },
+   { OPCODE_LIT,    "LIT",   1 },
+   { OPCODE_LOG,    "LOG",   1 },
+   { OPCODE_LRP,    "LRP",   3 },
+   { OPCODE_MAD,    "MAD",   3 },
+   { OPCODE_MAX,    "MAX",   2 },
+   { OPCODE_MIN,    "MIN",   2 },
+   { OPCODE_MOV,    "MOV",   1 },
+   { OPCODE_MUL,    "MUL",   2 },
+   { OPCODE_PK2H,   "PK2H",  1 },
+   { OPCODE_PK2US,  "PK2US", 1 },
+   { OPCODE_PK4B,   "PK4B",  1 },
+   { OPCODE_PK4UB,  "PK4UB", 1 },
+   { OPCODE_POW,    "POW",   2 },
+   { OPCODE_POPA,   "POPA",  0 },
+   { OPCODE_PRINT,  "PRINT", 1 },
+   { OPCODE_PUSHA,  "PUSHA", 0 },
+   { OPCODE_RCC,    "RCC",   1 },
+   { OPCODE_RCP,    "RCP",   1 },
+   { OPCODE_RET,    "RET",   0 },
+   { OPCODE_RFL,    "RFL",   1 },
+   { OPCODE_RSQ,    "RSQ",   1 },
+   { OPCODE_SCS,    "SCS",   1 },
+   { OPCODE_SEQ,    "SEQ",   2 },
+   { OPCODE_SFL,    "SFL",   0 },
+   { OPCODE_SGE,    "SGE",   2 },
+   { OPCODE_SGT,    "SGT",   2 },
+   { OPCODE_SIN,    "SIN",   1 },
+   { OPCODE_SLE,    "SLE",   2 },
+   { OPCODE_SLT,    "SLT",   2 },
+   { OPCODE_SNE,    "SNE",   2 },
+   { OPCODE_SSG,    "SSG",   1 },
+   { OPCODE_STR,    "STR",   0 },
+   { OPCODE_SUB,    "SUB",   2 },
+   { OPCODE_SWZ,    "SWZ",   1 },
+   { OPCODE_TEX,    "TEX",   1 },
+   { OPCODE_TXB,    "TXB",   1 },
+   { OPCODE_TXD,    "TXD",   3 },
+   { OPCODE_TXL,    "TXL",   1 },
+   { OPCODE_TXP,    "TXP",   1 },
+   { OPCODE_TXP_NV, "TXP",   1 },
+   { OPCODE_UP2H,   "UP2H",  1 },
+   { OPCODE_UP2US,  "UP2US", 1 },
+   { OPCODE_UP4B,   "UP4B",  1 },
+   { OPCODE_UP4UB,  "UP4UB", 1 },
+   { OPCODE_X2D,    "X2D",   3 },
+   { OPCODE_XPD,    "XPD",   2 }
+};
+
+
+/**
+ * Return the number of src registers for the given instruction/opcode.
+ */
+GLuint
+_mesa_num_inst_src_regs(gl_inst_opcode opcode)
+{
+   ASSERT(opcode == InstInfo[opcode].Opcode);
+   ASSERT(OPCODE_XPD == InstInfo[OPCODE_XPD].Opcode);
+   return InstInfo[opcode].NumSrcRegs;
+}
+
+
+/**
+ * Return string name for given program opcode.
+ */
+const char *
+_mesa_opcode_string(gl_inst_opcode opcode)
+{
+   ASSERT(opcode < MAX_OPCODE);
+   return InstInfo[opcode].Name;
+}
+
+/**
+ * Return string name for given program/register file.
+ */
+static const char *
+program_file_string(enum register_file f)
+{
+   switch (f) {
+   case PROGRAM_TEMPORARY:
+      return "TEMP";
+   case PROGRAM_LOCAL_PARAM:
+      return "LOCAL";
+   case PROGRAM_ENV_PARAM:
+      return "ENV";
+   case PROGRAM_STATE_VAR:
+      return "STATE";
+   case PROGRAM_INPUT:
+      return "INPUT";
+   case PROGRAM_OUTPUT:
+      return "OUTPUT";
+   case PROGRAM_NAMED_PARAM:
+      return "NAMED";
+   case PROGRAM_CONSTANT:
+      return "CONST";
+   case PROGRAM_UNIFORM:
+      return "UNIFORM";
+   case PROGRAM_VARYING:
+      return "VARYING";
+   case PROGRAM_WRITE_ONLY:
+      return "WRITE_ONLY";
+   case PROGRAM_ADDRESS:
+      return "ADDR";
+   default:
+      return "Unknown program file!";
+   }
+}
+
+
+/**
+ * Return a string representation of the given swizzle word.
+ * If extended is true, use extended (comma-separated) format.
+ */
+static const char *
+swizzle_string(GLuint swizzle, GLuint negateBase, GLboolean extended)
+{
+   static const char swz[] = "xyzw01";
+   static char s[20];
+   GLuint i = 0;
+
+   if (!extended && swizzle == SWIZZLE_NOOP && negateBase == 0)
+      return ""; /* no swizzle/negation */
+
+   if (!extended)
+      s[i++] = '.';
+
+   if (negateBase & 0x1)
+      s[i++] = '-';
+   s[i++] = swz[GET_SWZ(swizzle, 0)];
+
+   if (extended) {
+      s[i++] = ',';
+   }
+
+   if (negateBase & 0x2)
+      s[i++] = '-';
+   s[i++] = swz[GET_SWZ(swizzle, 1)];
+
+   if (extended) {
+      s[i++] = ',';
+   }
+
+   if (negateBase & 0x4)
+      s[i++] = '-';
+   s[i++] = swz[GET_SWZ(swizzle, 2)];
+
+   if (extended) {
+      s[i++] = ',';
+   }
+
+   if (negateBase & 0x8)
+      s[i++] = '-';
+   s[i++] = swz[GET_SWZ(swizzle, 3)];
+
+   s[i] = 0;
+   return s;
+}
+
+
+static const char *
+writemask_string(GLuint writeMask)
+{
+   static char s[10];
+   GLuint i = 0;
+
+   if (writeMask == WRITEMASK_XYZW)
+      return "";
+
+   s[i++] = '.';
+   if (writeMask & WRITEMASK_X)
+      s[i++] = 'x';
+   if (writeMask & WRITEMASK_Y)
+      s[i++] = 'y';
+   if (writeMask & WRITEMASK_Z)
+      s[i++] = 'z';
+   if (writeMask & WRITEMASK_W)
+      s[i++] = 'w';
+
+   s[i] = 0;
+   return s;
+}
+
+static void
+print_dst_reg(const struct prog_dst_register *dstReg)
+{
+   _mesa_printf(" %s[%d]%s",
+                program_file_string((enum register_file) dstReg->File),
+                dstReg->Index,
+                writemask_string(dstReg->WriteMask));
+}
+
+static void
+print_src_reg(const struct prog_src_register *srcReg)
+{
+   _mesa_printf("%s[%d]%s",
+                program_file_string((enum register_file) srcReg->File),
+                srcReg->Index,
+                swizzle_string(srcReg->Swizzle,
+                               srcReg->NegateBase, GL_FALSE));
+}
+
+static void
+print_comment(const struct prog_instruction *inst)
+{
+   if (inst->Comment)
+      _mesa_printf(";  # %s\n", inst->Comment);
+   else
+      _mesa_printf(";\n");
+}
+
+
+void
+_mesa_print_alu_instruction(const struct prog_instruction *inst,
+                           const char *opcode_string, 
+                           GLuint numRegs)
+{
+   GLuint j;
+
+   _mesa_printf("%s", opcode_string);
+
+   /* frag prog only */
+   if (inst->SaturateMode == SATURATE_ZERO_ONE)
+      _mesa_printf("_SAT");
+
+   if (inst->DstReg.File != PROGRAM_UNDEFINED) {
+      _mesa_printf(" %s[%d]%s",
+                  program_file_string((enum register_file) inst->DstReg.File),
+                  inst->DstReg.Index,
+                  writemask_string(inst->DstReg.WriteMask));
+   }
+   else {
+      _mesa_printf(" ???");
+   }
+
+   if (numRegs > 0)
+      _mesa_printf(", ");
+
+   for (j = 0; j < numRegs; j++) {
+      print_src_reg(inst->SrcReg + j);
+      if (j + 1 < numRegs)
+        _mesa_printf(", ");
+   }
+
+   if (inst->Comment)
+      _mesa_printf("  # %s", inst->Comment);
+
+   print_comment(inst);
+}
+
+
+/**
+ * Print a single vertex/fragment program instruction.
+ */
+void
+_mesa_print_instruction(const struct prog_instruction *inst)
+{
+   switch (inst->Opcode) {
+   case OPCODE_PRINT:
+      _mesa_printf("PRINT '%s'", inst->Data);
+      if (inst->SrcReg[0].File != PROGRAM_UNDEFINED) {
+         _mesa_printf(", ");
+         _mesa_printf("%s[%d]%s",
+                      program_file_string((enum register_file) inst->SrcReg[0].File),
+                      inst->SrcReg[0].Index,
+                      swizzle_string(inst->SrcReg[0].Swizzle,
+                                     inst->SrcReg[0].NegateBase, GL_FALSE));
+      }
+      if (inst->Comment)
+         _mesa_printf("  # %s", inst->Comment);
+      print_comment(inst);
+      break;
+   case OPCODE_SWZ:
+      _mesa_printf("SWZ");
+      if (inst->SaturateMode == SATURATE_ZERO_ONE)
+         _mesa_printf("_SAT");
+      print_dst_reg(&inst->DstReg);
+      _mesa_printf("%s[%d], %s",
+                   program_file_string((enum register_file) inst->SrcReg[0].File),
+                   inst->SrcReg[0].Index,
+                   swizzle_string(inst->SrcReg[0].Swizzle,
+                                  inst->SrcReg[0].NegateBase, GL_TRUE));
+      print_comment(inst);
+      break;
+   case OPCODE_TEX:
+   case OPCODE_TXP:
+   case OPCODE_TXB:
+      _mesa_printf("%s", _mesa_opcode_string(inst->Opcode));
+      if (inst->SaturateMode == SATURATE_ZERO_ONE)
+         _mesa_printf("_SAT");
+      _mesa_printf(" ");
+      print_dst_reg(&inst->DstReg);
+      _mesa_printf(", ");
+      print_src_reg(&inst->SrcReg[0]);
+      _mesa_printf(", texture[%d], ", inst->TexSrcUnit);
+      switch (inst->TexSrcTarget) {
+      case TEXTURE_1D_INDEX:   _mesa_printf("1D");    break;
+      case TEXTURE_2D_INDEX:   _mesa_printf("2D");    break;
+      case TEXTURE_3D_INDEX:   _mesa_printf("3D");    break;
+      case TEXTURE_CUBE_INDEX: _mesa_printf("CUBE");  break;
+      case TEXTURE_RECT_INDEX: _mesa_printf("RECT");  break;
+      default:
+         ;
+      }
+      print_comment(inst);
+      break;
+   case OPCODE_ARL:
+      _mesa_printf("ARL addr.x, ");
+      print_src_reg(&inst->SrcReg[0]);
+      print_comment(inst);
+      break;
+   case OPCODE_BRA:
+      _mesa_printf("BRA %u", inst->BranchTarget);
+      print_comment(inst);
+      break;
+   case OPCODE_CAL:
+      _mesa_printf("CAL %u", inst->BranchTarget);
+      print_comment(inst);
+      break;
+   case OPCODE_END:
+      _mesa_printf("END");
+      print_comment(inst);
+      break;
+   /* XXX may need other special-case instructions */
+   default:
+      /* typical alu instruction */
+      _mesa_print_alu_instruction(inst,
+                                 _mesa_opcode_string(inst->Opcode),
+                                 _mesa_num_inst_src_regs(inst->Opcode));
+      break;
+   }
+}
+
+
+/**
+ * Print a vertx/fragment program to stdout.
+ * XXX this function could be greatly improved.
+ */
+void
+_mesa_print_program(const struct gl_program *prog)
+{
+   GLuint i;
+   for (i = 0; i < prog->NumInstructions; i++) {
+      _mesa_printf("%3d: ", i);
+      _mesa_print_instruction(prog->Instructions + i);
+   }
+}
+
+
+/**
+ * Print all of a program's parameters.
+ */
+void
+_mesa_print_program_parameters(GLcontext *ctx, const struct gl_program *prog)
+{
+   GLint i;
+
+   _mesa_printf("InputsRead: 0x%x\n", prog->InputsRead);
+   _mesa_printf("OutputsWritten: 0x%x\n", prog->OutputsWritten);
+   _mesa_printf("NumInstructions=%d\n", prog->NumInstructions);
+   _mesa_printf("NumTemporaries=%d\n", prog->NumTemporaries);
+   _mesa_printf("NumParameters=%d\n", prog->NumParameters);
+   _mesa_printf("NumAttributes=%d\n", prog->NumAttributes);
+   _mesa_printf("NumAddressRegs=%d\n", prog->NumAddressRegs);
+       
+   _mesa_load_state_parameters(ctx, prog->Parameters);
+                       
+#if 0
+   _mesa_printf("Local Params:\n");
+   for (i = 0; i < MAX_PROGRAM_LOCAL_PARAMS; i++){
+      const GLfloat *p = prog->LocalParams[i];
+      _mesa_printf("%2d: %f, %f, %f, %f\n", i, p[0], p[1], p[2], p[3]);
+   }
+#endif 
+
+   for (i = 0; i < prog->Parameters->NumParameters; i++){
+      struct gl_program_parameter *param = prog->Parameters->Parameters + i;
+      const GLfloat *v = prog->Parameters->ParameterValues[i];
+      _mesa_printf("param[%d] %s %s = {%.3f, %.3f, %.3f, %.3f};\n",
+                   i,
+                   program_file_string(prog->Parameters->Parameters[i].Type),
+                   param->Name, v[0], v[1], v[2], v[3]);
+   }
+}
diff --git a/src/mesa/shader/prog_print.h b/src/mesa/shader/prog_print.h
new file mode 100644 (file)
index 0000000..595a0dc
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5.3
+ *
+ * Copyright (C) 1999-2006  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"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef PROG_PRINT_H
+#define PROG_PRINT_H
+
+
+extern void
+_mesa_print_instruction(const struct prog_instruction *inst);
+
+extern void
+_mesa_print_alu_instruction(const struct prog_instruction *inst,
+                           const char *opcode_string, 
+                           GLuint numRegs);
+
+extern void
+_mesa_print_program(const struct gl_program *prog);
+
+extern void
+_mesa_print_program_parameters(GLcontext *ctx, const struct gl_program *prog);
+
+
+#endif /* PROG_PRINT_H */
diff --git a/src/mesa/shader/prog_statevars.c b/src/mesa/shader/prog_statevars.c
new file mode 100644 (file)
index 0000000..7377c7d
--- /dev/null
@@ -0,0 +1,783 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5.3
+ *
+ * Copyright (C) 1999-2006  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"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file prog_statevars.c
+ * Program state variable management.
+ * \author Brian Paul
+ */
+
+
+#include "glheader.h"
+#include "context.h"
+#include "hash.h"
+#include "imports.h"
+#include "macros.h"
+#include "mtypes.h"
+#include "prog_statevars.h"
+#include "prog_parameter.h"
+#include "nvvertparse.h"
+
+
+/**
+ * Use the list of tokens in the state[] array to find global GL state
+ * and return it in <value>.  Usually, four values are returned in <value>
+ * but matrix queries may return as many as 16 values.
+ * This function is used for ARB vertex/fragment programs.
+ * The program parser will produce the state[] values.
+ */
+static void
+_mesa_fetch_state(GLcontext *ctx, const gl_state_index state[],
+                  GLfloat *value)
+{
+   switch (state[0]) {
+   case STATE_MATERIAL:
+      {
+         /* state[1] is either 0=front or 1=back side */
+         const GLuint face = (GLuint) state[1];
+         const struct gl_material *mat = &ctx->Light.Material;
+         ASSERT(face == 0 || face == 1);
+         /* we rely on tokens numbered so that _BACK_ == _FRONT_+ 1 */
+         ASSERT(MAT_ATTRIB_FRONT_AMBIENT + 1 == MAT_ATTRIB_BACK_AMBIENT);
+         /* XXX we could get rid of this switch entirely with a little
+          * work in arbprogparse.c's parse_state_single_item().
+          */
+         /* state[2] is the material attribute */
+         switch (state[2]) {
+         case STATE_AMBIENT:
+            COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_AMBIENT + face]);
+            return;
+         case STATE_DIFFUSE:
+            COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_DIFFUSE + face]);
+            return;
+         case STATE_SPECULAR:
+            COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_SPECULAR + face]);
+            return;
+         case STATE_EMISSION:
+            COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_EMISSION + face]);
+            return;
+         case STATE_SHININESS:
+            value[0] = mat->Attrib[MAT_ATTRIB_FRONT_SHININESS + face][0];
+            value[1] = 0.0F;
+            value[2] = 0.0F;
+            value[3] = 1.0F;
+            return;
+         default:
+            _mesa_problem(ctx, "Invalid material state in fetch_state");
+            return;
+         }
+      }
+   case STATE_LIGHT:
+      {
+         /* state[1] is the light number */
+         const GLuint ln = (GLuint) state[1];
+         /* state[2] is the light attribute */
+         switch (state[2]) {
+         case STATE_AMBIENT:
+            COPY_4V(value, ctx->Light.Light[ln].Ambient);
+            return;
+         case STATE_DIFFUSE:
+            COPY_4V(value, ctx->Light.Light[ln].Diffuse);
+            return;
+         case STATE_SPECULAR:
+            COPY_4V(value, ctx->Light.Light[ln].Specular);
+            return;
+         case STATE_POSITION:
+            COPY_4V(value, ctx->Light.Light[ln].EyePosition);
+            return;
+         case STATE_ATTENUATION:
+            value[0] = ctx->Light.Light[ln].ConstantAttenuation;
+            value[1] = ctx->Light.Light[ln].LinearAttenuation;
+            value[2] = ctx->Light.Light[ln].QuadraticAttenuation;
+            value[3] = ctx->Light.Light[ln].SpotExponent;
+            return;
+         case STATE_SPOT_DIRECTION:
+            COPY_3V(value, ctx->Light.Light[ln].EyeDirection);
+            value[3] = ctx->Light.Light[ln]._CosCutoff;
+            return;
+         case STATE_HALF:
+            {
+               GLfloat eye_z[] = {0, 0, 1};
+                                       
+               /* Compute infinite half angle vector:
+                *   half-vector = light_position + (0, 0, 1) 
+                * and then normalize.  w = 0
+               *
+               * light.EyePosition.w should be 0 for infinite lights.
+                */
+              ADD_3V(value, eye_z, ctx->Light.Light[ln].EyePosition);
+              NORMALIZE_3FV(value);
+              value[3] = 0;
+            }                                            
+            return;
+        case STATE_POSITION_NORMALIZED:
+            COPY_4V(value, ctx->Light.Light[ln].EyePosition);
+           NORMALIZE_3FV( value );
+            return;
+         default:
+            _mesa_problem(ctx, "Invalid light state in fetch_state");
+            return;
+         }
+      }
+   case STATE_LIGHTMODEL_AMBIENT:
+      COPY_4V(value, ctx->Light.Model.Ambient);
+      return;
+   case STATE_LIGHTMODEL_SCENECOLOR:
+      if (state[1] == 0) {
+         /* front */
+         GLint i;
+         for (i = 0; i < 3; i++) {
+            value[i] = ctx->Light.Model.Ambient[i]
+               * ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT][i]
+               + ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION][i];
+         }
+        value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
+      }
+      else {
+         /* back */
+         GLint i;
+         for (i = 0; i < 3; i++) {
+            value[i] = ctx->Light.Model.Ambient[i]
+               * ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_AMBIENT][i]
+               + ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_EMISSION][i];
+         }
+        value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
+      }
+      return;
+   case STATE_LIGHTPROD:
+      {
+         const GLuint ln = (GLuint) state[1];
+         const GLuint face = (GLuint) state[2];
+         GLint i;
+         ASSERT(face == 0 || face == 1);
+         switch (state[3]) {
+            case STATE_AMBIENT:
+               for (i = 0; i < 3; i++) {
+                  value[i] = ctx->Light.Light[ln].Ambient[i] *
+                     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];
+               return;
+            case STATE_DIFFUSE:
+               for (i = 0; i < 3; i++) {
+                  value[i] = ctx->Light.Light[ln].Diffuse[i] *
+                     ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE+face][i];
+               }
+               /* [3] = material alpha */
+               value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE+face][3];
+               return;
+            case STATE_SPECULAR:
+               for (i = 0; i < 3; i++) {
+                  value[i] = ctx->Light.Light[ln].Specular[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];
+               return;
+            default:
+               _mesa_problem(ctx, "Invalid lightprod state in fetch_state");
+               return;
+         }
+      }
+   case STATE_TEXGEN:
+      {
+         /* state[1] is the texture unit */
+         const GLuint unit = (GLuint) state[1];
+         /* state[2] is the texgen attribute */
+         switch (state[2]) {
+         case STATE_TEXGEN_EYE_S:
+            COPY_4V(value, ctx->Texture.Unit[unit].EyePlaneS);
+            return;
+         case STATE_TEXGEN_EYE_T:
+            COPY_4V(value, ctx->Texture.Unit[unit].EyePlaneT);
+            return;
+         case STATE_TEXGEN_EYE_R:
+            COPY_4V(value, ctx->Texture.Unit[unit].EyePlaneR);
+            return;
+         case STATE_TEXGEN_EYE_Q:
+            COPY_4V(value, ctx->Texture.Unit[unit].EyePlaneQ);
+            return;
+         case STATE_TEXGEN_OBJECT_S:
+            COPY_4V(value, ctx->Texture.Unit[unit].ObjectPlaneS);
+            return;
+         case STATE_TEXGEN_OBJECT_T:
+            COPY_4V(value, ctx->Texture.Unit[unit].ObjectPlaneT);
+            return;
+         case STATE_TEXGEN_OBJECT_R:
+            COPY_4V(value, ctx->Texture.Unit[unit].ObjectPlaneR);
+            return;
+         case STATE_TEXGEN_OBJECT_Q:
+            COPY_4V(value, ctx->Texture.Unit[unit].ObjectPlaneQ);
+            return;
+         default:
+            _mesa_problem(ctx, "Invalid texgen state in fetch_state");
+            return;
+         }
+      }
+   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);
+      return;
+   case STATE_FOG_PARAMS:
+      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);
+      return;
+   case STATE_CLIPPLANE:
+      {
+         const GLuint plane = (GLuint) state[1];
+         COPY_4V(value, ctx->Transform.EyeUserPlane[plane]);
+      }
+      return;
+   case STATE_POINT_SIZE:
+      value[0] = ctx->Point.Size;
+      value[1] = ctx->Point.MinSize;
+      value[2] = ctx->Point.MaxSize;
+      value[3] = ctx->Point.Threshold;
+      return;
+   case STATE_POINT_ATTENUATION:
+      value[0] = ctx->Point.Params[0];
+      value[1] = ctx->Point.Params[1];
+      value[2] = ctx->Point.Params[2];
+      value[3] = 1.0F;
+      return;
+   case STATE_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 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 GLfloat *m;
+         GLuint row, i;
+         if (mat == STATE_MODELVIEW) {
+            matrix = ctx->ModelviewMatrixStack.Top;
+         }
+         else if (mat == STATE_PROJECTION) {
+            matrix = ctx->ProjectionMatrixStack.Top;
+         }
+         else if (mat == STATE_MVP) {
+            matrix = &ctx->_ModelProjectMatrix;
+         }
+         else if (mat == STATE_TEXTURE) {
+            matrix = ctx->TextureMatrixStack[index].Top;
+         }
+         else if (mat == STATE_PROGRAM) {
+            matrix = ctx->ProgramMatrixStack[index].Top;
+         }
+         else {
+            _mesa_problem(ctx, "Bad matrix name in _mesa_fetch_state()");
+            return;
+         }
+         if (modifier == STATE_MATRIX_INVERSE ||
+             modifier == STATE_MATRIX_INVTRANS) {
+            /* Be sure inverse is up to date:
+            */
+            _math_matrix_alloc_inv( (GLmatrix *) matrix );
+           _math_matrix_analyse( (GLmatrix*) matrix );
+            m = matrix->inv;
+         }
+         else {
+            m = matrix->m;
+         }
+         if (modifier == STATE_MATRIX_TRANSPOSE ||
+             modifier == STATE_MATRIX_INVTRANS) {
+            for (i = 0, row = firstRow; row <= lastRow; row++) {
+               value[i++] = m[row * 4 + 0];
+               value[i++] = m[row * 4 + 1];
+               value[i++] = m[row * 4 + 2];
+               value[i++] = m[row * 4 + 3];
+            }
+         }
+         else {
+            for (i = 0, row = firstRow; row <= lastRow; row++) {
+               value[i++] = m[row + 0];
+               value[i++] = m[row + 4];
+               value[i++] = m[row + 8];
+               value[i++] = m[row + 12];
+            }
+         }
+      }
+      return;
+   case STATE_DEPTH_RANGE:
+      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;
+      return;
+   case STATE_FRAGMENT_PROGRAM:
+      {
+         /* state[1] = {STATE_ENV, STATE_LOCAL} */
+         /* state[2] = parameter index          */
+         const int idx = (int) state[2];
+         switch (state[1]) {
+            case STATE_ENV:
+               COPY_4V(value, ctx->FragmentProgram.Parameters[idx]);
+               break;
+            case STATE_LOCAL:
+               COPY_4V(value, ctx->FragmentProgram.Current->Base.LocalParams[idx]);
+               break;
+            default:
+               _mesa_problem(ctx, "Bad state switch in _mesa_fetch_state()");
+               return;
+         }
+      }
+      return;
+               
+   case STATE_VERTEX_PROGRAM:
+      {
+         /* state[1] = {STATE_ENV, STATE_LOCAL} */
+         /* state[2] = parameter index          */
+         const int idx = (int) state[2];
+         switch (state[1]) {
+            case STATE_ENV:
+               COPY_4V(value, ctx->VertexProgram.Parameters[idx]);
+               break;
+            case STATE_LOCAL:
+               COPY_4V(value, ctx->VertexProgram.Current->Base.LocalParams[idx]);
+               break;
+            default:
+               _mesa_problem(ctx, "Bad state switch in _mesa_fetch_state()");
+               return;
+         }
+      }
+      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;
+         }
+      }
+      return;
+
+   default:
+      _mesa_problem(ctx, "Invalid state in _mesa_fetch_state");
+      return;
+   }
+}
+
+
+/**
+ * Return a bitmask of the Mesa state flags (_NEW_* values) which would
+ * indicate that the given context state may have changed.
+ * The bitmask is used during validation to determine if we need to update
+ * vertex/fragment program parameters (like "state.material.color") when
+ * some GL state has changed.
+ */
+GLbitfield
+_mesa_program_state_flags(const GLint state[])
+{
+   switch (state[0]) {
+   case STATE_MATERIAL:
+   case STATE_LIGHT:
+   case STATE_LIGHTMODEL_AMBIENT:
+   case STATE_LIGHTMODEL_SCENECOLOR:
+   case STATE_LIGHTPROD:
+      return _NEW_LIGHT;
+
+   case STATE_TEXGEN:
+   case STATE_TEXENV_COLOR:
+      return _NEW_TEXTURE;
+
+   case STATE_FOG_COLOR:
+   case STATE_FOG_PARAMS:
+      return _NEW_FOG;
+
+   case STATE_CLIPPLANE:
+      return _NEW_TRANSFORM;
+
+   case STATE_POINT_SIZE:
+   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_DEPTH_RANGE:
+      return _NEW_VIEWPORT;
+
+   case STATE_FRAGMENT_PROGRAM:
+   case STATE_VERTEX_PROGRAM:
+      return _NEW_PROGRAM;
+
+   case STATE_INTERNAL:
+      switch (state[1]) {
+      case STATE_NORMAL_SCALE:
+        return _NEW_MODELVIEW;
+      case STATE_TEXRECT_SCALE:
+        return _NEW_TEXTURE;
+      default:
+         /* unknown state indexes are silently ignored and
+         *  no flag set, since it is handled by the driver.
+         */
+        return 0;
+      }
+
+   default:
+      _mesa_problem(NULL, "unexpected state[0] in make_state_flags()");
+      return 0;
+   }
+}
+
+
+static void
+append(char *dst, const char *src)
+{
+   while (*dst)
+      dst++;
+   while (*src)
+     *dst++ = *src++;
+   *dst = 0;
+}
+
+
+static void
+append_token(char *dst, gl_state_index k)
+{
+   switch (k) {
+   case STATE_MATERIAL:
+      append(dst, "material.");
+      break;
+   case STATE_LIGHT:
+      append(dst, "light");
+      break;
+   case STATE_LIGHTMODEL_AMBIENT:
+      append(dst, "lightmodel.ambient");
+      break;
+   case STATE_LIGHTMODEL_SCENECOLOR:
+      break;
+   case STATE_LIGHTPROD:
+      append(dst, "lightprod");
+      break;
+   case STATE_TEXGEN:
+      append(dst, "texgen");
+      break;
+   case STATE_FOG_COLOR:
+      append(dst, "fog.color");
+      break;
+   case STATE_FOG_PARAMS:
+      append(dst, "fog.params");
+      break;
+   case STATE_CLIPPLANE:
+      append(dst, "clip");
+      break;
+   case STATE_POINT_SIZE:
+      append(dst, "point.size");
+      break;
+   case STATE_POINT_ATTENUATION:
+      append(dst, "point.attenuation");
+      break;
+   case STATE_MATRIX:
+      append(dst, "matrix.");
+      break;
+   case STATE_MODELVIEW:
+      append(dst, "modelview");
+      break;
+   case STATE_PROJECTION:
+      append(dst, "projection");
+      break;
+   case STATE_MVP:
+      append(dst, "mvp");
+      break;
+   case STATE_TEXTURE:
+      append(dst, "texture");
+      break;
+   case STATE_PROGRAM:
+      append(dst, "program");
+      break;
+   case STATE_MATRIX_INVERSE:
+      append(dst, ".inverse");
+      break;
+   case STATE_MATRIX_TRANSPOSE:
+      append(dst, ".transpose");
+      break;
+   case STATE_MATRIX_INVTRANS:
+      append(dst, ".invtrans");
+      break;
+   case STATE_AMBIENT:
+      append(dst, "ambient");
+      break;
+   case STATE_DIFFUSE:
+      append(dst, "diffuse");
+      break;
+   case STATE_SPECULAR:
+      append(dst, "specular");
+      break;
+   case STATE_EMISSION:
+      append(dst, "emission");
+      break;
+   case STATE_SHININESS:
+      append(dst, "shininess");
+      break;
+   case STATE_HALF:
+      append(dst, "half");
+      break;
+   case STATE_POSITION:
+      append(dst, ".position");
+      break;
+   case STATE_ATTENUATION:
+      append(dst, ".attenuation");
+      break;
+   case STATE_SPOT_DIRECTION:
+      append(dst, ".spot.direction");
+      break;
+   case STATE_TEXGEN_EYE_S:
+      append(dst, "eye.s");
+      break;
+   case STATE_TEXGEN_EYE_T:
+      append(dst, "eye.t");
+      break;
+   case STATE_TEXGEN_EYE_R:
+      append(dst, "eye.r");
+      break;
+   case STATE_TEXGEN_EYE_Q:
+      append(dst, "eye.q");
+      break;
+   case STATE_TEXGEN_OBJECT_S:
+      append(dst, "object.s");
+      break;
+   case STATE_TEXGEN_OBJECT_T:
+      append(dst, "object.t");
+      break;
+   case STATE_TEXGEN_OBJECT_R:
+      append(dst, "object.r");
+      break;
+   case STATE_TEXGEN_OBJECT_Q:
+      append(dst, "object.q");
+      break;
+   case STATE_TEXENV_COLOR:
+      append(dst, "texenv");
+      break;
+   case STATE_DEPTH_RANGE:
+      append(dst, "depth.range");
+      break;
+   case STATE_VERTEX_PROGRAM:
+   case STATE_FRAGMENT_PROGRAM:
+      break;
+   case STATE_ENV:
+      append(dst, "env");
+      break;
+   case STATE_LOCAL:
+      append(dst, "local");
+      break;
+   case STATE_INTERNAL:
+   case STATE_NORMAL_SCALE:
+   case STATE_POSITION_NORMALIZED:
+      append(dst, "(internal)");
+      break;
+   default:
+      ;
+   }
+}
+
+static void
+append_face(char *dst, GLint face)
+{
+   if (face == 0)
+      append(dst, "front.");
+   else
+      append(dst, "back.");
+}
+
+static void
+append_index(char *dst, GLint index)
+{
+   char s[20];
+   _mesa_sprintf(s, "[%d].", index);
+   append(dst, s);
+}
+
+/**
+ * Make a string from the given state vector.
+ * For example, return "state.matrix.texture[2].inverse".
+ * Use _mesa_free() to deallocate the string.
+ */
+const char *
+_mesa_program_state_string(const GLint state[6])
+{
+   char str[1000] = "";
+   char tmp[30];
+
+   append(str, "state.");
+   append_token(str, (gl_state_index) state[0]);
+
+   switch (state[0]) {
+   case STATE_MATERIAL:
+      append_face(str, state[1]);
+      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;
+   case STATE_LIGHTMODEL_AMBIENT:
+      append(str, "lightmodel.ambient");
+      break;
+   case STATE_LIGHTMODEL_SCENECOLOR:
+      if (state[1] == 0) {
+         append(str, "lightmodel.front.scenecolor");
+      }
+      else {
+         append(str, "lightmodel.back.scenecolor");
+      }
+      break;
+   case STATE_LIGHTPROD:
+      append_index(str, state[1]); /* light number [i]. */
+      append_face(str, state[2]);
+      append_token(str, (gl_state_index) state[3]);
+      break;
+   case STATE_TEXGEN:
+      append_index(str, state[1]); /* tex unit [i] */
+      append_token(str, (gl_state_index) state[2]); /* plane coef */
+      break;
+   case STATE_TEXENV_COLOR:
+      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:
+      {
+         /* 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)
+            append_index(str, index);
+         if (modifier)
+            append_token(str, modifier);
+         if (firstRow == lastRow)
+            _mesa_sprintf(tmp, ".row[%d]", firstRow);
+         else
+            _mesa_sprintf(tmp, ".row[%d..%d]", firstRow, lastRow);
+         append(str, tmp);
+      }
+      break;
+   case STATE_DEPTH_RANGE:
+      break;
+   case STATE_FRAGMENT_PROGRAM:
+   case STATE_VERTEX_PROGRAM:
+      /* state[1] = {STATE_ENV, STATE_LOCAL} */
+      /* state[2] = parameter index          */
+      append_token(str, (gl_state_index) state[1]);
+      append_index(str, state[2]);
+      break;
+   case STATE_INTERNAL:
+      break;
+   default:
+      _mesa_problem(NULL, "Invalid state in _mesa_program_state_string");
+      break;
+   }
+
+   return _mesa_strdup(str);
+}
+
+
+/**
+ * Loop over all the parameters in a parameter list.  If the parameter
+ * is a GL state reference, look up the current value of that state
+ * variable and put it into the parameter's Value[4] array.
+ * This would be called at glBegin time when using a fragment program.
+ */
+void
+_mesa_load_state_parameters(GLcontext *ctx,
+                            struct gl_program_parameter_list *paramList)
+{
+   GLuint i;
+
+   if (!paramList)
+      return;
+
+   for (i = 0; i < paramList->NumParameters; i++) {
+      if (paramList->Parameters[i].Type == PROGRAM_STATE_VAR) {
+         _mesa_fetch_state(ctx, 
+                          paramList->Parameters[i].StateIndexes,
+                           paramList->ParameterValues[i]);
+      }
+   }
+}
+
diff --git a/src/mesa/shader/prog_statevars.h b/src/mesa/shader/prog_statevars.h
new file mode 100644 (file)
index 0000000..17e3805
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5.2
+ *
+ * Copyright (C) 1999-2006  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"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef PROG_STATEVARS_H
+#define PROG_STATEVARS_H
+
+#include "mtypes.h"
+
+
+/**
+ * Used for describing GL state referenced from inside ARB vertex and
+ * fragment programs.
+ * A string such as "state.light[0].ambient" gets translated into a
+ * sequence of tokens such as [ STATE_LIGHT, 0, STATE_AMBIENT ].
+ */
+typedef enum gl_state_index_ {
+   STATE_MATERIAL = 100,  /* start at 100 so small ints are seen as ints */
+
+   STATE_LIGHT,
+   STATE_LIGHTMODEL_AMBIENT,
+   STATE_LIGHTMODEL_SCENECOLOR,
+   STATE_LIGHTPROD,
+
+   STATE_TEXGEN,
+
+   STATE_FOG_COLOR,
+   STATE_FOG_PARAMS,
+
+   STATE_CLIPPLANE,
+
+   STATE_POINT_SIZE,
+   STATE_POINT_ATTENUATION,
+
+   STATE_MATRIX,
+   STATE_MODELVIEW,
+   STATE_PROJECTION,
+   STATE_MVP,
+   STATE_TEXTURE,
+   STATE_PROGRAM,
+   STATE_MATRIX_INVERSE,
+   STATE_MATRIX_TRANSPOSE,
+   STATE_MATRIX_INVTRANS,
+
+   STATE_AMBIENT,
+   STATE_DIFFUSE,
+   STATE_SPECULAR,
+   STATE_EMISSION,
+   STATE_SHININESS,
+   STATE_HALF, 
+
+   STATE_POSITION,
+   STATE_ATTENUATION,
+   STATE_SPOT_DIRECTION,
+
+   STATE_TEXGEN_EYE_S,
+   STATE_TEXGEN_EYE_T,
+   STATE_TEXGEN_EYE_R,
+   STATE_TEXGEN_EYE_Q,
+   STATE_TEXGEN_OBJECT_S,
+   STATE_TEXGEN_OBJECT_T,
+   STATE_TEXGEN_OBJECT_R,
+   STATE_TEXGEN_OBJECT_Q,
+
+   STATE_TEXENV_COLOR,
+       
+   STATE_DEPTH_RANGE,
+
+   STATE_VERTEX_PROGRAM,
+   STATE_FRAGMENT_PROGRAM,
+
+   STATE_ENV,
+   STATE_LOCAL,
+
+   STATE_INTERNAL,             /* Mesa additions */
+   STATE_NORMAL_SCALE,
+   STATE_TEXRECT_SCALE,
+   STATE_POSITION_NORMALIZED,   /* normalized light position */
+   STATE_INTERNAL_DRIVER       /* first available state index for drivers (must be last) */
+} gl_state_index;
+
+
+
+extern void
+_mesa_load_state_parameters(GLcontext *ctx,
+                            struct gl_program_parameter_list *paramList);
+
+
+extern GLbitfield
+_mesa_program_state_flags(const GLint state[]);
+
+
+extern const char *
+_mesa_program_state_string(const GLint state[6]);
+
+
+#endif /* PROG_STATEVARS_H */