OSDN Git Service

Moved some shared vertex/fragment program code into new program.c file.
authorBrian Paul <brian.paul@tungstengraphics.com>
Sun, 31 Aug 2003 18:52:47 +0000 (18:52 +0000)
committerBrian Paul <brian.paul@tungstengraphics.com>
Sun, 31 Aug 2003 18:52:47 +0000 (18:52 +0000)
Implemented new program_parameter_list type and functions for dealing with
named program parameters, constants and GL state references.
New state_index enum for describing GL state referenced within ARB vertex/
fragment programs.  Plus, functions for fetching named GL state.

18 files changed:
src/mesa/main/Makefile.X11
src/mesa/main/arbfragparse.h
src/mesa/main/arbprogram.c
src/mesa/main/arbprogram.h
src/mesa/main/context.c
src/mesa/main/descrip.mms
src/mesa/main/dlist.c
src/mesa/main/main.dsp
src/mesa/main/mtypes.h
src/mesa/main/nvfragparse.c
src/mesa/main/nvfragprog.h
src/mesa/main/nvprogram.c
src/mesa/main/nvprogram.h
src/mesa/main/nvvertparse.c
src/mesa/main/nvvertprog.h
src/mesa/main/program.c [new file with mode: 0644]
src/mesa/main/program.h [new file with mode: 0644]
src/mesa/main/state.c

index d918656..1f9bd66 100644 (file)
@@ -62,6 +62,7 @@ CORE_SOURCES = \
        pixel.c \
        points.c \
        polygon.c \
+       program.c \
        rastpos.c \
        state.c \
        stencil.c \
index ad6d8ef..17e8dcf 100644 (file)
@@ -25,6 +25,8 @@
 #ifndef ARBFRAGPARSE_H
 #define ARBFRAGPARSE_H
 
+#include "mtypes.h"
+
 extern void
 _mesa_parse_arb_fragment_program(GLcontext * ctx, GLenum target,
                                  const GLubyte * str, GLsizei len,
index 07ba462..4e40d27 100644 (file)
 #include "nvvertprog.h"
 
 
-/*
- * Init context's program state
- */
-void
-_mesa_init_program(GLcontext *ctx)
-{
-   GLuint i;
-
-   ctx->Program.ErrorPos = -1;
-   ctx->Program.ErrorString = _mesa_strdup("");
-
-#if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program
-   ctx->VertexProgram.Enabled = GL_FALSE;
-   ctx->VertexProgram.PointSizeEnabled = GL_FALSE;
-   ctx->VertexProgram.TwoSideEnabled = GL_FALSE;
-   ctx->VertexProgram.Current = NULL;
-   ctx->VertexProgram.Current = (struct vertex_program *) ctx->Shared->DefaultVertexProgram;
-   assert(ctx->VertexProgram.Current);
-   ctx->VertexProgram.Current->Base.RefCount++;
-   for (i = 0; i < MAX_NV_VERTEX_PROGRAM_PARAMS / 4; i++) {
-      ctx->VertexProgram.TrackMatrix[i] = GL_NONE;
-      ctx->VertexProgram.TrackMatrixTransform[i] = GL_IDENTITY_NV;
-   }
-#endif
-
-#if FEATURE_NV_fragment_program || FEATURE_ARB_fragment_program
-   ctx->FragmentProgram.Enabled = GL_FALSE;
-   ctx->FragmentProgram.Current = (struct fragment_program *) ctx->Shared->DefaultFragmentProgram;
-   assert(ctx->FragmentProgram.Current);
-   ctx->FragmentProgram.Current->Base.RefCount++;
-#endif
-}
-
-
 void
 _mesa_EnableVertexAttribArrayARB(GLuint index)
 {
index 07cd3a1..bc5a662 100644 (file)
 #ifndef ARBPROGRAM_H
 #define ARBPROGRAM_H
 
-#include "mtypes.h"
-
-extern void
-_mesa_init_program(GLcontext *ctx);
-
 
 extern void
 _mesa_EnableVertexAttribArrayARB(GLuint index);
index 8e5884a..9151c74 100644 (file)
@@ -74,7 +74,6 @@
 #include "glheader.h"
 #include "imports.h"
 #include "accum.h"
-#include "arbprogram.h"
 #include "attrib.h"
 #include "blend.h"
 #include "buffers.h"
 #include "texstate.h"
 #include "mtypes.h"
 #include "varray.h"
-#if FEATURE_NV_vertex_program
-#include "nvprogram.h"
+#if FEATURE_NV_vertex_program || FEATURE_NV_fragment_program
+#include "program.h"
 #endif
 #include "vtxfmt.h"
 #if _HAVE_FULL_GL
index 9cff58e..41b5fe5 100644 (file)
@@ -59,6 +59,7 @@ SOURCES =accum.c \
        pixel.c \
        points.c \
        polygon.c \
+       program.c \
        rastpos.c \
        state.c \
        stencil.c \
@@ -116,6 +117,7 @@ occlude.obj,\
 pixel.obj,\
 points.obj,\
 polygon.obj,\
+program.obj,\
 rastpos.obj,\
 state.obj,\
 stencil.obj,\
@@ -187,6 +189,7 @@ occlude.obj : occlude.c
 pixel.obj : pixel.c
 points.obj : points.c
 polygon.obj : polygon.c
+program.obj : program.c
 rastpos.obj : rastpos.c
 state.obj : state.c
 stencil.obj : stencil.c
index abfc2df..36809fb 100644 (file)
@@ -34,6 +34,7 @@
 #include "config.h"
 #if FEATURE_ARB_vertex_program || FEATURE_ARB_fragment_program
 #include "arbprogram.h"
+#include "program.h"
 #endif
 #include "attrib.h"
 #include "blend.h"
@@ -71,6 +72,7 @@
 #include "varray.h"
 #if FEATURE_NV_vertex_program || FEATURE_NV_fragment_program
 #include "nvprogram.h"
+#include "program.h"
 #endif
 
 #include "math/m_matrix.h"
@@ -6509,9 +6511,9 @@ _mesa_init_dlist_table( struct _glapi_table *table, GLuint tableSize )
     * VertexAttribPointerNV, GetProgram*, GetVertexAttrib*
     */
    table->BindProgramNV = save_BindProgramNV;
-   table->DeleteProgramsNV = _mesa_DeleteProgramsNV;
+   table->DeleteProgramsNV = _mesa_DeletePrograms;
    table->ExecuteProgramNV = save_ExecuteProgramNV;
-   table->GenProgramsNV = _mesa_GenProgramsNV;
+   table->GenProgramsNV = _mesa_GenPrograms;
    table->AreProgramsResidentNV = _mesa_AreProgramsResidentNV;
    table->RequestResidentProgramsNV = save_RequestResidentProgramsNV;
    table->GetProgramParameterfvNV = _mesa_GetProgramParameterfvNV;
@@ -6523,7 +6525,7 @@ _mesa_init_dlist_table( struct _glapi_table *table, GLuint tableSize )
    table->GetVertexAttribfvNV = _mesa_GetVertexAttribfvNV;
    table->GetVertexAttribivNV = _mesa_GetVertexAttribivNV;
    table->GetVertexAttribPointervNV = _mesa_GetVertexAttribPointervNV;
-   table->IsProgramNV = _mesa_IsProgramNV;
+   table->IsProgramNV = _mesa_IsProgram;
    table->LoadProgramNV = save_LoadProgramNV;
    table->ProgramParameter4dNV = save_ProgramParameter4dNV;
    table->ProgramParameter4dvNV = save_ProgramParameter4dvNV;
index 72d7edd..9f1537f 100644 (file)
@@ -265,6 +265,10 @@ SOURCE=.\polygon.c
 # End Source File
 # Begin Source File
 
+SOURCE=.\program.c
+# End Source File
+# Begin Source File
+
 SOURCE=.\rastpos.c
 # End Source File
 # Begin Source File
@@ -525,6 +529,10 @@ SOURCE=.\polygon.h
 # End Source File
 # Begin Source File
 
+SOURCE=.\program.h
+# End Source File
+# Begin Source File
+
 SOURCE=.\rastpos.h
 # End Source File
 # Begin Source File
index 5497aac..47cb19b 100644 (file)
@@ -1445,16 +1445,7 @@ enum register_file
 struct vp_instruction;
 struct fp_instruction;
 
-
-/**
- * Named program parameters 
- */
-struct program_parameter
-{
-   const char *Name;
-   GLfloat Values[4];
-   GLboolean Constant;
-};
+struct program_parameter_list;
 
 
 /**
@@ -1499,8 +1490,7 @@ struct fragment_program
    GLuint NumAluInstructions; /**< GL_ARB_fragment_program */
    GLuint NumTexInstructions;
    GLuint NumTexIndirections;
-   struct program_parameter *Parameters; /**< array [NumParameters] */
-   GLuint NumParameters;
+   struct program_parameter_list *Parameters; /**< array [NumParameters] */
 };
 
 
index 36840d0..cf631a5 100644 (file)
@@ -37,6 +37,7 @@
 #include "nvfragprog.h"
 #include "nvfragparse.h"
 #include "nvprogram.h"
+#include "program.h"
 
 
 #define INPUT_1V     1
@@ -136,11 +137,7 @@ struct parse_state {
    const GLubyte *curLine;
    struct fragment_program *program;  /* current program */
 
-   GLuint numParameters;
-   struct program_parameter *parameters; /* DECLARE */
-
-   GLuint numConstants;
-   struct program_parameter *constants; /* DEFINE */
+   struct program_parameter_list *parameters;
 
    GLuint numInst;                    /* number of instructions parsed */
    GLuint inputsRead;                 /* bitmask of input registers used */
@@ -149,69 +146,6 @@ struct parse_state {
 };
 
 
-/**
- * Add a new program parameter (via DEFINE statement)
- * \return index of the new entry in the parameter list
- */
-static GLuint
-add_parameter(struct parse_state *parseState,
-              const char *name, const GLfloat values[4], GLboolean constant)
-{
-   const GLuint n = parseState->numParameters;
-
-   parseState->parameters = _mesa_realloc(parseState->parameters,
-                                   n * sizeof(struct program_parameter),
-                                   (n + 1) * sizeof(struct program_parameter));
-   parseState->numParameters = n + 1;
-   parseState->parameters[n].Name = _mesa_strdup(name);
-   COPY_4V(parseState->parameters[n].Values, values);
-   parseState->parameters[n].Constant = constant;
-   return n;
-}
-
-
-/**
- * Add a new unnamed constant to the parameter lists.
- * \param parseState  parsing state
- * \param values  four float values
- * \return index of the new parameter.
- */
-static GLuint
-add_unnamed_constant(struct parse_state *parseState, const GLfloat values[4])
-{
-   /* generate a new dummy name */
-   static GLuint n = 0;
-   char name[20];
-   _mesa_sprintf(name, "constant%d", n);
-   n++;
-   /* store it */
-   return add_parameter(parseState, name, values, GL_TRUE);
-}
-
-
-static const GLfloat *
-lookup_parameter(struct parse_state *parseState, const char *name)
-{
-   GLuint i;
-   for (i = 0; i < parseState->numParameters; i++) {
-      if (_mesa_strcmp(parseState->parameters[i].Name, name) == 0)
-         return parseState->parameters[i].Values;
-   }
-   return NULL;
-}
-
-
-static const GLint
-lookup_parameter_index(struct parse_state *parseState, const char *name)
-{
-   GLuint i;
-   for (i = 0; i < parseState->numParameters; i++) {
-      if (_mesa_strcmp(parseState->parameters[i].Name, name) == 0)
-         return i;
-   }
-   return -1;
-}
-
 
 /*
  * Called whenever we find an error during parsing.
@@ -532,7 +466,8 @@ Parse_ScalarConstant(struct parse_state *parseState, GLfloat *number)
       const GLfloat *constant;
       if (!Parse_Identifier(parseState, ident))
          RETURN_ERROR1("Expected an identifier");
-      constant = lookup_parameter(parseState, (const char *) ident);
+      constant = _mesa_lookup_parameter_value(parseState->parameters,
+                                              -1, (const char *) ident);
       /* XXX Check that it's a constant and not a parameter */
       if (!constant) {
          RETURN_ERROR1("Undefined symbol");
@@ -1078,7 +1013,8 @@ Parse_VectorSrc(struct parse_state *parseState,
       GLint paramIndex;
       if (!Parse_Identifier(parseState, ident))
          RETURN_ERROR;
-      paramIndex = lookup_parameter_index(parseState, (const char *) ident);
+      paramIndex = _mesa_lookup_parameter_index(parseState->parameters,
+                                                -1, (const char *) ident);
       if (paramIndex < 0) {
          RETURN_ERROR2("Undefined constant or parameter: ", ident);
       }
@@ -1091,7 +1027,7 @@ Parse_VectorSrc(struct parse_state *parseState,
       GLuint paramIndex;
       if (!Parse_ScalarConstant(parseState, values))
          RETURN_ERROR;
-      paramIndex = add_unnamed_constant(parseState, values);
+      paramIndex = _mesa_add_unnamed_constant(parseState->parameters, values);
       srcReg->File = PROGRAM_NAMED_PARAM;
       srcReg->Index = paramIndex;
    }
@@ -1102,7 +1038,7 @@ Parse_VectorSrc(struct parse_state *parseState,
       (void) Parse_String(parseState, "{");
       if (!Parse_VectorConstant(parseState, values))
          RETURN_ERROR;
-      paramIndex = add_unnamed_constant(parseState, values);
+      paramIndex = _mesa_add_unnamed_constant(parseState->parameters, values);
       srcReg->File = PROGRAM_NAMED_PARAM;
       srcReg->Index = paramIndex;      
    }
@@ -1188,7 +1124,7 @@ Parse_ScalarSrcReg(struct parse_state *parseState,
       (void) Parse_String(parseState, "{");
       if (!Parse_VectorConstant(parseState, values))
          RETURN_ERROR;
-      paramIndex = add_unnamed_constant(parseState, values);
+      paramIndex = _mesa_add_unnamed_constant(parseState->parameters, values);
       srcReg->File = PROGRAM_NAMED_PARAM;
       srcReg->Index = paramIndex;      
    }
@@ -1198,7 +1134,7 @@ Parse_ScalarSrcReg(struct parse_state *parseState,
       GLuint paramIndex;
       if (!Parse_ScalarConstant(parseState, values))
          RETURN_ERROR;
-      paramIndex = add_unnamed_constant(parseState, values);
+      paramIndex = _mesa_add_unnamed_constant(parseState->parameters, values);
       srcReg->Index = paramIndex;      
       srcReg->File = PROGRAM_NAMED_PARAM;
       needSuffix = GL_FALSE;
@@ -1278,10 +1214,12 @@ Parse_InstructionSequence(struct parse_state *parseState,
             RETURN_ERROR;
          if (!Parse_String(parseState, ";"))
             RETURN_ERROR1("Expected ;");
-         if (lookup_parameter(parseState, (const char *) id)) {
+         if (_mesa_lookup_parameter_index(parseState->parameters,
+                                          -1, (const char *) id) >= 0) {
             RETURN_ERROR2(id, "already defined");
          }
-         add_parameter(parseState, (const char *) id, value, GL_TRUE);
+         _mesa_add_named_parameter(parseState->parameters,
+                                   (const char *) id, value);
       }
       else if (Parse_String(parseState, "DECLARE")) {
          GLubyte id[100];
@@ -1295,10 +1233,12 @@ Parse_InstructionSequence(struct parse_state *parseState,
          }
          if (!Parse_String(parseState, ";"))
             RETURN_ERROR1("Expected ;");
-         if (lookup_parameter(parseState, (const char *) id)) {
+         if (_mesa_lookup_parameter_index(parseState->parameters,
+                                          -1, (const char *) id) >= 0) {
             RETURN_ERROR2(id, "already declared");
          }
-         add_parameter(parseState, (const char *) id, value, GL_FALSE);
+         _mesa_add_named_parameter(parseState->parameters,
+                                   (const char *) id, value);
       }
       else if (Parse_String(parseState, "END")) {
          inst->Opcode = FP_OPCODE_END;
@@ -1461,6 +1401,7 @@ _mesa_parse_nv_fragment_program(GLcontext *ctx, GLenum dstTarget,
    parseState.program = program;
    parseState.numInst = 0;
    parseState.curLine = programString;
+   parseState.parameters = _mesa_new_parameter_list();
 
    /* Reset error state */
    _mesa_set_program_error(ctx, -1, NULL);
@@ -1530,24 +1471,8 @@ _mesa_parse_nv_fragment_program(GLcontext *ctx, GLenum dstTarget,
          program->TexturesUsed[u] = parseState.texturesUsed[u];
 
       /* save program parameters */
-      if (program->Parameters) {
-         GLuint i;
-         for (i = 0; i < program->NumParameters; i++)
-            _mesa_free((void *) program->Parameters[i].Name);
-         _mesa_free(program->Parameters);
-      }
-      program->NumParameters = parseState.numParameters;
       program->Parameters = parseState.parameters;
 
-      /* free program constants */
-      if (parseState.constants) {
-         GLuint i;
-         for (i = 0; i < parseState.numConstants; i++)
-            _mesa_free((void *) parseState.constants[i].Name);
-         _mesa_free(parseState.constants);
-      }
-         
-
       /* allocate registers for declared program parameters */
 #if 00
       _mesa_assign_program_registers(&(program->SymbolTable));
@@ -1583,15 +1508,17 @@ PrintSrcReg(const struct fragment_program *program,
       _mesa_printf("-");
    }
    if (src->File == PROGRAM_NAMED_PARAM) {
-      if (program->Parameters[src->Index].Constant) {
+      if (program->Parameters->Parameters[src->Index].Type == CONSTANT) {
          printf("{%g, %g, %g, %g}",
-                program->Parameters[src->Index].Values[0],
-                program->Parameters[src->Index].Values[1],
-                program->Parameters[src->Index].Values[2],
-                program->Parameters[src->Index].Values[3]);
+                program->Parameters->Parameters[src->Index].Values[0],
+                program->Parameters->Parameters[src->Index].Values[1],
+                program->Parameters->Parameters[src->Index].Values[2],
+                program->Parameters->Parameters[src->Index].Values[3]);
       }
       else {
-         printf("%s", program->Parameters[src->Index].Name);
+         ASSERT(program->Parameters->Parameters[src->Index].Type
+                == NAMED_PARAMETER);
+         printf("%s", program->Parameters->Parameters[src->Index].Name);
       }
    }
    else if (src->File == PROGRAM_OUTPUT) {
index 33b219c..cf5253b 100644 (file)
@@ -25,6 +25,8 @@
 
 /* Private fragment program types and constants only used by files
  * related to fragment programs.
+ *
+ * XXX TO-DO: Rename this file "fragprog.h" since it's not NV-specific.
  */
 
 
index 61dca50..a4af0eb 100644 (file)
 #include "nvvertparse.h"
 #include "nvvertprog.h"
 #include "nvprogram.h"
+#include "program.h"
 
 
-/**
- * Set the vertex/fragment program error state (position and error string).
- * This is generally called from within the parsers.
- */
-void
-_mesa_set_program_error(GLcontext *ctx, GLint pos, const char *string)
-{
-   ctx->Program.ErrorPos = pos;
-   _mesa_free((void *) ctx->Program.ErrorString);
-   if (!string)
-      string = "";
-   ctx->Program.ErrorString = _mesa_strdup(string);
-}
-
-
-/**
- * Find the line number and column for 'pos' within 'string'.
- * Return a copy of the line which contains 'pos'.  Free the line with
- * _mesa_free().
- * \param string  the program string
- * \param pos     the position within the string
- * \param line    returns the line number corresponding to 'pos'.
- * \param col     returns the column number corresponding to 'pos'.
- * \return copy of the line containing 'pos'.
- */
-const GLubyte *
-_mesa_find_line_column(const GLubyte *string, const GLubyte *pos,
-                       GLint *line, GLint *col)
-{
-   const GLubyte *lineStart = string;
-   const GLubyte *p = string;
-   GLubyte *s;
-   int len;
-
-   *line = 1;
-
-   while (p != pos) {
-      if (*p == (GLubyte) '\n') {
-         (*line)++;
-         lineStart = p + 1;
-      }
-      p++;
-   }
-
-   *col = (pos - lineStart) + 1;
-
-   /* return copy of this line */
-   while (*p != 0 && *p != '\n')
-      p++;
-   len = p - lineStart;
-   s = (GLubyte *) _mesa_malloc(len + 1);
-   _mesa_memcpy(s, lineStart, len);
-   s[len] = 0;
-
-   return s;
-}
-
-
-
-/**
- * Allocate and initialize a new fragment/vertex program object
- * \param ctx  context
- * \param id   program id/number
- * \param target  program target/type
- * \return  pointer to new program object
- */
-struct program *
-_mesa_alloc_program(GLcontext *ctx, GLenum target, GLuint id)
-{
-   struct program *prog;
-
-   if (target == GL_VERTEX_PROGRAM_NV
-       || target == GL_VERTEX_PROGRAM_ARB) {
-      struct vertex_program *vprog = CALLOC_STRUCT(vertex_program);
-      if (!vprog) {
-         return NULL;
-      }
-      prog = &(vprog->Base);
-   }
-   else if (target == GL_FRAGMENT_PROGRAM_NV
-            || target == GL_FRAGMENT_PROGRAM_ARB) {
-      struct fragment_program *fprog = CALLOC_STRUCT(fragment_program);
-      if (!fprog) {
-         return NULL;
-      }
-      prog = &(fprog->Base);
-   }
-   else {
-      _mesa_problem(ctx, "bad target in _mesa_alloc_program");
-      return NULL;
-   }
-   prog->Id = id;
-   prog->Target = target;
-   prog->Resident = GL_TRUE;
-   prog->RefCount = 1;
-   return prog;
-}
-
-
-/**
- * Delete a program and remove it from the hash table, ignoring the
- * reference count.
- * \note Called from the GL API dispatcher.
- */
-void
-_mesa_delete_program(GLcontext *ctx, struct program *prog)
-{
-   ASSERT(prog);
-
-   if (prog->String)
-      _mesa_free(prog->String);
-   if (prog->Target == GL_VERTEX_PROGRAM_NV ||
-       prog->Target == GL_VERTEX_STATE_PROGRAM_NV) {
-      struct vertex_program *vprog = (struct vertex_program *) prog;
-      if (vprog->Instructions)
-         _mesa_free(vprog->Instructions);
-   }
-   else if (prog->Target == GL_FRAGMENT_PROGRAM_NV) {
-      struct fragment_program *fprog = (struct fragment_program *) prog;
-      if (fprog->Instructions)
-         _mesa_free(fprog->Instructions);
-      if (fprog->Parameters) {
-         GLuint i;
-         for (i = 0; i < fprog->NumParameters; i++) {
-            _mesa_free((void *) fprog->Parameters[i].Name);
-         }
-         _mesa_free(fprog->Parameters);
-      }
-   }
-   _mesa_free(prog);
-}
-
-
-/**
- * Bind a program (make it current)
- * \note Called from the GL API dispatcher by both glBindProgramNV
- * and glBindProgramARB.
- */
-void
-_mesa_BindProgramNV(GLenum target, GLuint id)
-{
-   struct program *prog;
-   GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   if ((target == GL_VERTEX_PROGRAM_NV
-        && ctx->Extensions.NV_vertex_program) ||
-       (target == GL_VERTEX_PROGRAM_ARB
-        && ctx->Extensions.ARB_vertex_program)) {
-      if (ctx->VertexProgram.Current &&
-          ctx->VertexProgram.Current->Base.Id == id)
-         return;
-      /* decrement refcount on previously bound vertex program */
-      if (ctx->VertexProgram.Current) {
-         ctx->VertexProgram.Current->Base.RefCount--;
-         /* and delete if refcount goes below one */
-         if (ctx->VertexProgram.Current->Base.RefCount <= 0) {
-            _mesa_delete_program(ctx, &(ctx->VertexProgram.Current->Base));
-            _mesa_HashRemove(ctx->Shared->Programs, id);
-         }
-      }
-   }
-   else if ((target == GL_FRAGMENT_PROGRAM_NV
-             && ctx->Extensions.NV_fragment_program) ||
-            (target == GL_FRAGMENT_PROGRAM_ARB
-             && ctx->Extensions.ARB_fragment_program)) {
-      if (ctx->FragmentProgram.Current &&
-          ctx->FragmentProgram.Current->Base.Id == id)
-         return;
-      /* decrement refcount on previously bound fragment program */
-      if (ctx->FragmentProgram.Current) {
-         ctx->FragmentProgram.Current->Base.RefCount--;
-         /* and delete if refcount goes below one */
-         if (ctx->FragmentProgram.Current->Base.RefCount <= 0) {
-            _mesa_delete_program(ctx, &(ctx->FragmentProgram.Current->Base));
-            _mesa_HashRemove(ctx->Shared->Programs, id);
-         }
-      }
-   }
-   else {
-      _mesa_error(ctx, GL_INVALID_ENUM, "glBindProgramNV/ARB(target)");
-      return;
-   }
-
-   /* NOTE: binding to a non-existant program is not an error.
-    * That's supposed to be caught in glBegin.
-    */
-   if (id == 0) {
-      /* default program */
-      prog = NULL;
-      if (target == GL_VERTEX_PROGRAM_NV || target == GL_VERTEX_PROGRAM_ARB)
-         prog = ctx->Shared->DefaultVertexProgram;
-      else
-         prog = ctx->Shared->DefaultFragmentProgram;
-   }
-   else {
-      prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, id);
-      if (prog) {
-         if (prog->Target == 0) {
-            /* prog was allocated with glGenProgramsNV */
-            prog->Target = target;
-         }
-         else if (prog->Target != target) {
-            _mesa_error(ctx, GL_INVALID_OPERATION,
-                        "glBindProgramNV/ARB(target mismatch)");
-            return;
-         }
-      }
-      else {
-         /* allocate a new program now */
-         prog = _mesa_alloc_program(ctx, target, id);
-         if (!prog) {
-            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindProgramNV/ARB");
-            return;
-         }
-         prog->Id = id;
-         prog->Target = target;
-         prog->Resident = GL_TRUE;
-         prog->RefCount = 1;
-         _mesa_HashInsert(ctx->Shared->Programs, id, prog);
-      }
-   }
-
-   /* bind now */
-   if (target == GL_VERTEX_PROGRAM_NV || target == GL_VERTEX_PROGRAM_ARB) {
-      ctx->VertexProgram.Current = (struct vertex_program *) prog;
-   }
-   else if (target == GL_FRAGMENT_PROGRAM_NV || target == GL_FRAGMENT_PROGRAM_ARB) {
-      ctx->FragmentProgram.Current = (struct fragment_program *) prog;
-   }
-
-   if (prog)
-      prog->RefCount++;
-}
-
-
-/**
- * Delete a list of programs.
- * \note Not compiled into display lists.
- * \note Called by both glDeleteProgramsNV and glDeleteProgramsARB.
- */
-void
-_mesa_DeleteProgramsNV(GLsizei n, const GLuint *ids)
-{
-   GLint i;
-   GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   if (n < 0) {
-      _mesa_error( ctx, GL_INVALID_VALUE, "glDeleteProgramsNV" );
-      return;
-   }
-
-   for (i = 0; i < n; i++) {
-      if (ids[i] != 0) {
-         struct program *prog = (struct program *)
-            _mesa_HashLookup(ctx->Shared->Programs, ids[i]);
-         if (prog) {
-            if (prog->Target == GL_VERTEX_PROGRAM_NV ||
-                prog->Target == GL_VERTEX_STATE_PROGRAM_NV) {
-               if (ctx->VertexProgram.Current &&
-                   ctx->VertexProgram.Current->Base.Id == ids[i]) {
-                  /* unbind this currently bound program */
-                  _mesa_BindProgramNV(prog->Target, 0);
-               }
-            }
-            else if (prog->Target == GL_FRAGMENT_PROGRAM_NV) {
-               if (ctx->FragmentProgram.Current &&
-                   ctx->FragmentProgram.Current->Base.Id == ids[i]) {
-                  /* unbind this currently bound program */
-                  _mesa_BindProgramNV(prog->Target, 0);
-               }
-            }
-            else {
-               _mesa_problem(ctx, "bad target in glDeleteProgramsNV");
-               return;
-            }
-            prog->RefCount--;
-            if (prog->RefCount <= 0) {
-               _mesa_delete_program(ctx, prog);
-            }
-         }
-      }
-   }
-}
-
 
 /**
  * Execute a vertex state program.
@@ -362,49 +77,6 @@ _mesa_ExecuteProgramNV(GLenum target, GLuint id, const GLfloat *params)
 
 
 /**
- * Generate a list of new program identifiers.
- * \note Not compiled into display lists.
- * \note Called by both glGenProgramsNV and glGenProgramsARB.
- */
-void
-_mesa_GenProgramsNV(GLsizei n, GLuint *ids)
-{
-   GLuint first;
-   GLuint i;
-   GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   if (n < 0) {
-      _mesa_error(ctx, GL_INVALID_VALUE, "glGenPrograms");
-      return;
-   }
-
-   if (!ids)
-      return;
-
-   first = _mesa_HashFindFreeKeyBlock(ctx->Shared->Programs, n);
-
-   for (i = 0; i < (GLuint) n; i++) {
-      const int bytes = MAX2(sizeof(struct vertex_program),
-                             sizeof(struct fragment_program));
-      struct program *prog = (struct program *) _mesa_calloc(bytes);
-      if (!prog) {
-         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenPrograms");
-         return;
-      }
-      prog->RefCount = 1;
-      prog->Id = first + i;
-      _mesa_HashInsert(ctx->Shared->Programs, first + i, prog);
-   }
-
-   /* Return the program names */
-   for (i = 0; i < (GLuint) n; i++) {
-      ids[i] = first + i;
-   }
-}
-
-
-/**
  * Determine if a set of programs is resident in hardware.
  * \note Not compiled into display lists.
  * \note Called from the GL API dispatcher.
@@ -816,30 +488,6 @@ _mesa_GetVertexAttribPointervNV(GLuint index, GLenum pname, GLvoid **pointer)
 }
 
 
-/**
- * Determine if id names a program.
- * \note Not compiled into display lists.
- * \note Called from both glIsProgramNV and glIsProgramARB.
- * \param id is the program identifier
- * \return GL_TRUE if id is a program, else GL_FALSE.
- */
-GLboolean
-_mesa_IsProgramNV(GLuint id)
-{
-   struct program *prog;
-   GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
-
-   if (id == 0)
-      return GL_FALSE;
-
-   prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, id);
-   if (prog && prog->Target)
-      return GL_TRUE;
-   else
-      return GL_FALSE;
-}
-
 
 /**
  * Load/parse/compile a program.
@@ -1101,7 +749,8 @@ _mesa_ProgramNamedParameter4fNV(GLuint id, GLsizei len, const GLubyte *name,
 {
    struct program *prog;
    struct fragment_program *fragProg;
-   GLuint i;
+   GLfloat *v;
+
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
@@ -1117,17 +766,13 @@ _mesa_ProgramNamedParameter4fNV(GLuint id, GLsizei len, const GLubyte *name,
    }
 
    fragProg = (struct fragment_program *) prog;
-   for (i = 0; i < fragProg->NumParameters; i++) {
-      if (!_mesa_strncmp(fragProg->Parameters[i].Name,
-                         (const char *) name, len) &&
-          fragProg->Parameters[i].Name[len] == 0) {
-         ASSERT(!fragProg->Parameters[i].Constant);
-         fragProg->Parameters[i].Values[0] = x;
-         fragProg->Parameters[i].Values[1] = y;
-         fragProg->Parameters[i].Values[2] = z;
-         fragProg->Parameters[i].Values[3] = w;
-         return;
-      }
+   v = _mesa_lookup_parameter_value(fragProg->Parameters, len, (char *) name);
+   if (v) {
+      v[0] = x;
+      v[1] = y;
+      v[2] = z;
+      v[3] = w;
+      return;
    }
 
    _mesa_error(ctx, GL_INVALID_VALUE, "glProgramNamedParameterNV");
@@ -1167,7 +812,8 @@ _mesa_GetProgramNamedParameterfvNV(GLuint id, GLsizei len, const GLubyte *name,
 {
    struct program *prog;
    struct fragment_program *fragProg;
-   GLuint i;
+   const GLfloat *v;
+
    GET_CURRENT_CONTEXT(ctx);
 
    if (!ctx->_CurrentProgram)
@@ -1185,17 +831,13 @@ _mesa_GetProgramNamedParameterfvNV(GLuint id, GLsizei len, const GLubyte *name,
    }
 
    fragProg = (struct fragment_program *) prog;
-   for (i = 0; i < fragProg->NumParameters; i++) {
-      if (!_mesa_strncmp(fragProg->Parameters[i].Name,
-                         (const char *) name, len) &&
-          fragProg->Parameters[i].Name[len] == 0) {
-         ASSERT(!fragProg->Parameters[i].Constant);
-         params[0] = fragProg->Parameters[i].Values[0];
-         params[1] = fragProg->Parameters[i].Values[1];
-         params[2] = fragProg->Parameters[i].Values[2];
-         params[3] = fragProg->Parameters[i].Values[3];
-         return;
-      }
+   v = _mesa_lookup_parameter_value(fragProg->Parameters, len, (char *) name);
+   if (v) {
+      params[0] = v[0];
+      params[1] = v[1];
+      params[2] = v[2];
+      params[3] = v[3];
+      return;
    }
 
    _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramNamedParameterNV");
index c9b8a83..f505a84 100644 (file)
 #define NVPROGRAM_H
 
 
-/** Internal functions **/
-extern void
-_mesa_set_program_error(GLcontext *ctx, GLint pos, const char *string);
-
-extern const GLubyte *
-_mesa_find_line_column(const GLubyte *string, const GLubyte *pos,
-                       GLint *line, GLint *col);
-
-extern struct program *
-_mesa_alloc_program(GLcontext *ctx, GLenum target, GLuint id);
-
-extern void
-_mesa_delete_program(GLcontext *ctx, struct program *prog);
-
-
-
-/** API functions **/
-
-extern void
-_mesa_BindProgramNV(GLenum target, GLuint id);
-
-extern void
-_mesa_DeleteProgramsNV(GLsizei n, const GLuint *ids);
-
 extern void
 _mesa_ExecuteProgramNV(GLenum target, GLuint id, const GLfloat *params);
 
-extern void
-_mesa_GenProgramsNV(GLsizei n, GLuint *ids);
-
 extern GLboolean
 _mesa_AreProgramsResidentNV(GLsizei n, const GLuint *ids, GLboolean *residences);
 
@@ -93,9 +66,6 @@ _mesa_GetVertexAttribivNV(GLuint index, GLenum pname, GLint *params);
 extern void
 _mesa_GetVertexAttribPointervNV(GLuint index, GLenum pname, GLvoid **pointer);
 
-extern GLboolean
-_mesa_IsProgramNV(GLuint id);
-
 extern void
 _mesa_LoadProgramNV(GLenum target, GLuint id, GLsizei len, const GLubyte *program);
 
@@ -145,32 +115,5 @@ extern void
 _mesa_GetProgramNamedParameterdvNV(GLuint id, GLsizei len, const GLubyte *name,
                                    GLdouble *params);
 
-#if 0
-extern void
-_mesa_ProgramLocalParameter4fARB(GLenum target, GLuint index,
-                                 GLfloat x, GLfloat y, GLfloat z, GLfloat w);
-
-extern void
-_mesa_ProgramLocalParameter4fvARB(GLenum target, GLuint index,
-                                  const GLfloat *params);
-
-extern void
-_mesa_ProgramLocalParameter4dARB(GLenum target, GLuint index,
-                                 GLdouble x, GLdouble y,
-                                 GLdouble z, GLdouble w);
-
-extern void
-_mesa_ProgramLocalParameter4dvARB(GLenum target, GLuint index,
-                                  const GLdouble *params);
-
-extern void
-_mesa_GetProgramLocalParameterfvARB(GLenum target, GLuint index,
-                                    GLfloat *params);
-
-extern void
-_mesa_GetProgramLocalParameterdvARB(GLenum target, GLuint index,
-                                    GLdouble *params);
-#endif
-
 
 #endif
index fd99a26..50316b3 100644 (file)
@@ -38,6 +38,8 @@
 #include "nvprogram.h"
 #include "nvvertparse.h"
 #include "nvvertprog.h"
+#include "program.h"
+
 
 /**
  * Current parsing state.  This structure is passed among the parsing
index 1011fc5..0dbee78 100644 (file)
@@ -25,6 +25,8 @@
 
 /* Private vertex program types and constants only used by files
  * related to vertex programs.
+ *
+ * XXX TO-DO: Rename this file "vertprog.h" since it's not NV-specific.
  */
 
 
diff --git a/src/mesa/main/program.c b/src/mesa/main/program.c
new file mode 100644 (file)
index 0000000..07ab420
--- /dev/null
@@ -0,0 +1,927 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  5.1
+ *
+ * Copyright (C) 1999-2003  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 program.c
+ * Vertex and fragment program support functions.
+ * \author Brian Paul
+ */
+
+
+#include "glheader.h"
+#include "context.h"
+#include "hash.h"
+#include "imports.h"
+#include "macros.h"
+#include "mtypes.h"
+#include "program.h"
+
+
+/**********************************************************************/
+/* Utility functions                                                  */
+/**********************************************************************/
+
+
+/**
+ * Init context's program state
+ */
+void
+_mesa_init_program(GLcontext *ctx)
+{
+   GLuint i;
+
+   ctx->Program.ErrorPos = -1;
+   ctx->Program.ErrorString = _mesa_strdup("");
+
+#if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program
+   ctx->VertexProgram.Enabled = GL_FALSE;
+   ctx->VertexProgram.PointSizeEnabled = GL_FALSE;
+   ctx->VertexProgram.TwoSideEnabled = GL_FALSE;
+   ctx->VertexProgram.Current = NULL;
+   ctx->VertexProgram.Current = (struct vertex_program *) ctx->Shared->DefaultVertexProgram;
+   assert(ctx->VertexProgram.Current);
+   ctx->VertexProgram.Current->Base.RefCount++;
+   for (i = 0; i < MAX_NV_VERTEX_PROGRAM_PARAMS / 4; i++) {
+      ctx->VertexProgram.TrackMatrix[i] = GL_NONE;
+      ctx->VertexProgram.TrackMatrixTransform[i] = GL_IDENTITY_NV;
+   }
+#endif
+
+#if FEATURE_NV_fragment_program || FEATURE_ARB_fragment_program
+   ctx->FragmentProgram.Enabled = GL_FALSE;
+   ctx->FragmentProgram.Current = (struct fragment_program *) ctx->Shared->DefaultFragmentProgram;
+   assert(ctx->FragmentProgram.Current);
+   ctx->FragmentProgram.Current->Base.RefCount++;
+#endif
+}
+
+
+/**
+ * Set the vertex/fragment program error state (position and error string).
+ * This is generally called from within the parsers.
+ */
+void
+_mesa_set_program_error(GLcontext *ctx, GLint pos, const char *string)
+{
+   ctx->Program.ErrorPos = pos;
+   _mesa_free((void *) ctx->Program.ErrorString);
+   if (!string)
+      string = "";
+   ctx->Program.ErrorString = _mesa_strdup(string);
+}
+
+
+/**
+ * Find the line number and column for 'pos' within 'string'.
+ * Return a copy of the line which contains 'pos'.  Free the line with
+ * _mesa_free().
+ * \param string  the program string
+ * \param pos     the position within the string
+ * \param line    returns the line number corresponding to 'pos'.
+ * \param col     returns the column number corresponding to 'pos'.
+ * \return copy of the line containing 'pos'.
+ */
+const GLubyte *
+_mesa_find_line_column(const GLubyte *string, const GLubyte *pos,
+                       GLint *line, GLint *col)
+{
+   const GLubyte *lineStart = string;
+   const GLubyte *p = string;
+   GLubyte *s;
+   int len;
+
+   *line = 1;
+
+   while (p != pos) {
+      if (*p == (GLubyte) '\n') {
+         (*line)++;
+         lineStart = p + 1;
+      }
+      p++;
+   }
+
+   *col = (pos - lineStart) + 1;
+
+   /* return copy of this line */
+   while (*p != 0 && *p != '\n')
+      p++;
+   len = p - lineStart;
+   s = (GLubyte *) _mesa_malloc(len + 1);
+   _mesa_memcpy(s, lineStart, len);
+   s[len] = 0;
+
+   return s;
+}
+
+
+
+/**
+ * Allocate and initialize a new fragment/vertex program object
+ * \param ctx  context
+ * \param id   program id/number
+ * \param target  program target/type
+ * \return  pointer to new program object
+ */
+struct program *
+_mesa_alloc_program(GLcontext *ctx, GLenum target, GLuint id)
+{
+   struct program *prog;
+
+   if (target == GL_VERTEX_PROGRAM_NV
+       || target == GL_VERTEX_PROGRAM_ARB) {
+      struct vertex_program *vprog = CALLOC_STRUCT(vertex_program);
+      if (!vprog) {
+         return NULL;
+      }
+      prog = &(vprog->Base);
+   }
+   else if (target == GL_FRAGMENT_PROGRAM_NV
+            || target == GL_FRAGMENT_PROGRAM_ARB) {
+      struct fragment_program *fprog = CALLOC_STRUCT(fragment_program);
+      if (!fprog) {
+         return NULL;
+      }
+      prog = &(fprog->Base);
+   }
+   else {
+      _mesa_problem(ctx, "bad target in _mesa_alloc_program");
+      return NULL;
+   }
+   prog->Id = id;
+   prog->Target = target;
+   prog->Resident = GL_TRUE;
+   prog->RefCount = 1;
+   return prog;
+}
+
+
+/**
+ * Delete a program and remove it from the hash table, ignoring the
+ * reference count.
+ * \note Called from the GL API dispatcher.
+ */
+void
+_mesa_delete_program(GLcontext *ctx, struct program *prog)
+{
+   ASSERT(prog);
+
+   if (prog->String)
+      _mesa_free(prog->String);
+   if (prog->Target == GL_VERTEX_PROGRAM_NV ||
+       prog->Target == GL_VERTEX_STATE_PROGRAM_NV) {
+      struct vertex_program *vprog = (struct vertex_program *) prog;
+      if (vprog->Instructions)
+         _mesa_free(vprog->Instructions);
+   }
+   else if (prog->Target == GL_FRAGMENT_PROGRAM_NV) {
+      struct fragment_program *fprog = (struct fragment_program *) prog;
+      if (fprog->Instructions)
+         _mesa_free(fprog->Instructions);
+      if (fprog->Parameters) {
+         _mesa_free_parameter_list(fprog->Parameters);
+      }
+   }
+   _mesa_free(prog);
+}
+
+
+
+/**********************************************************************/
+/* Program parameter functions                                        */
+/**********************************************************************/
+
+struct program_parameter_list *
+_mesa_new_parameter_list(void)
+{
+   return (struct program_parameter_list *)
+      _mesa_calloc(sizeof(struct program_parameter_list));
+}
+
+
+/**
+ * Free a parameter list and all its parameters
+ */
+void
+_mesa_free_parameter_list(struct program_parameter_list *paramList)
+{
+   _mesa_free_parameters(paramList);
+   _mesa_free(paramList);
+}
+
+
+/**
+ * Free all the parameters in the given list, but don't free the
+ * paramList structure itself.
+ */
+void
+_mesa_free_parameters(struct program_parameter_list *paramList)
+{
+   GLuint i;
+   for (i = 0; i < paramList->NumParameters; i++) {
+      _mesa_free((void *) paramList->Parameters[i].Name);
+   }
+   _mesa_free(paramList->Parameters);
+   paramList->NumParameters = 0;
+   paramList->Parameters = NULL;
+}
+
+
+/**
+ * Helper function used by the functions below.
+ */
+static GLint
+add_parameter(struct program_parameter_list *paramList,
+              const char *name, const GLfloat values[4],
+              enum parameter_type type)
+{
+   const GLuint n = paramList->NumParameters;
+
+   paramList->Parameters = _mesa_realloc(paramList->Parameters,
+                                   n * sizeof(struct program_parameter),
+                                   (n + 1) * sizeof(struct program_parameter));
+   if (!paramList->Parameters) {
+      /* out of memory */
+      paramList->NumParameters = 0;
+      return -1;
+   }
+   else {
+      paramList->NumParameters = n + 1;
+      paramList->Parameters[n].Name = _mesa_strdup(name);
+      paramList->Parameters[n].Type = type;
+      if (values)
+         COPY_4V(paramList->Parameters[n].Values, 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 program_parameter_list *paramList,
+                          const char *name, const GLfloat values[4])
+{
+   return add_parameter(paramList, name, values, NAMED_PARAMETER);
+}
+
+
+/**
+ * Add a new unnamed constant to the parameter list.
+ * \param paramList - the parameter list
+ * \param values - four float values
+ * \return index of the new parameter.
+ */
+GLint
+_mesa_add_named_constant(struct program_parameter_list *paramList,
+                         const char *name, const GLfloat values[4])
+{
+   return add_parameter(paramList, name, values, CONSTANT);
+}
+
+
+/**
+ * Add a new unnamed constant to the parameter list.
+ * \param paramList - the parameter list
+ * \param values - four float values
+ * \return index of the new parameter.
+ */
+GLint
+_mesa_add_unnamed_constant(struct program_parameter_list *paramList,
+                           const GLfloat values[4])
+{
+   /* generate a new dummy name */
+   static GLuint n = 0;
+   char name[20];
+   _mesa_sprintf(name, "constant%d", n);
+   n++;
+   /* store it */
+   return add_parameter(paramList, name, values, CONSTANT);
+}
+
+
+/**
+ * Add a new state reference to the parameter list.
+ * \param paramList - the parameter list
+ * \param values - four float values
+ * \return index of the new parameter.
+ */
+GLint
+_mesa_add_state_reference(struct program_parameter_list *paramList,
+                          const char *stateString)
+{
+   /* XXX Should we parse <stateString> here and produce the parameter's
+    * list of STATE_* tokens here, or in the parser?
+    */
+   return add_parameter(paramList, stateString, NULL, STATE);
+}
+
+
+/**
+ * Lookup a parameter value by name in the given parameter list.
+ * \return pointer to the float[4] values.
+ */
+GLfloat *
+_mesa_lookup_parameter_value(struct program_parameter_list *paramList,
+                             GLsizei nameLen, const char *name)
+{
+   GLuint i;
+
+   if (nameLen == -1) {
+      /* name is null-terminated */
+      for (i = 0; i < paramList->NumParameters; i++) {
+         if (_mesa_strcmp(paramList->Parameters[i].Name, name) == 0)
+            return paramList->Parameters[i].Values;
+      }
+   }
+   else {
+      /* name is not null-terminated, use nameLen */
+      for (i = 0; i < paramList->NumParameters; i++) {
+         if (_mesa_strncmp(paramList->Parameters[i].Name, name, nameLen) == 0
+             && _mesa_strlen(paramList->Parameters[i].Name) == nameLen)
+            return paramList->Parameters[i].Values;
+      }
+   }
+   return NULL;
+}
+
+
+/**
+ * Lookup a parameter index by name in the given parameter list.
+ * \return index of parameter in the list.
+ */
+GLint
+_mesa_lookup_parameter_index(struct program_parameter_list *paramList,
+                             GLsizei nameLen, const char *name)
+{
+   GLint i;
+
+   if (nameLen == -1) {
+      /* name is null-terminated */
+      for (i = 0; i < (GLint) paramList->NumParameters; i++) {
+         if (_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 (_mesa_strncmp(paramList->Parameters[i].Name, name, nameLen) == 0
+             && _mesa_strlen(paramList->Parameters[i].Name) == nameLen)
+            return i;
+      }
+   }
+   return -1;
+}
+
+
+/**
+ * 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 enum 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];
+         /* state[2] is the material attribute */
+         switch (state[2]) {
+         case STATE_AMBIENT:
+            if (face == 0)
+               COPY_4V(value, ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT]);
+            else
+               COPY_4V(value, ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_AMBIENT]);
+            return;
+         case STATE_DIFFUSE:
+            if (face == 0)
+               COPY_4V(value, ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE]);
+            else
+               COPY_4V(value, ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE]);
+            return;
+         case STATE_SPECULAR:
+            if (face == 0)
+               COPY_4V(value, ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SPECULAR]);
+            else
+               COPY_4V(value, ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_SPECULAR]);
+            return;
+         case STATE_EMISSION:
+            if (face == 0)
+               COPY_4V(value, ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION]);
+            else
+               COPY_4V(value, ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_EMISSION]);
+            return;
+         case STATE_SHININESS:
+            if (face == 0)
+               value[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SHININESS][0];
+            else
+               value[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_SHININESS][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;
+         }
+      };
+      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_4V(value, ctx->Light.Light[ln].EyeDirection);
+            return;
+         default:
+            _mesa_problem(ctx, "Invalid light state in fetch_state");
+            return;
+         }
+      }
+      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 < 4; 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];
+         }
+      }
+      else {
+         /* back */
+         GLint i;
+         for (i = 0; i < 4; 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];
+         }
+      }
+      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;
+         }
+      }
+      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;
+         }
+      }
+      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.End);
+      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 column to fetch */
+         /* state[4] = last column to fetch */
+         /* state[5] = transpose, inverse or invtrans */
+
+         const GLmatrix *matrix;
+         const enum state_index mat = state[1];
+         const GLuint index = (GLuint) state[2];
+         const GLuint first = (GLuint) state[3];
+         const GLuint last = (GLuint) state[4];
+         const enum 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) {
+            /* XXX be sure inverse is up to date */
+            m = matrix->inv;
+         }
+         else {
+            m = matrix->m;
+         }
+         if (modifier == STATE_MATRIX_TRANSPOSE ||
+             modifier == STATE_MATRIX_INVTRANS) {
+            for (i = 0, row = first; row <= last; 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 = first; row <= last; row++) {
+               value[i++] = m[row + 0];
+               value[i++] = m[row + 4];
+               value[i++] = m[row + 8];
+               value[i++] = m[row + 12];
+            }
+         }
+      }
+      return;
+   default:
+      _mesa_problem(ctx, "Invalid state in fetch_state");
+      return;
+   }
+}
+
+
+/**
+ * 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 program_parameter_list *paramList)
+{
+   GLuint i;
+   for (i = 0; i < paramList->NumParameters; i++) {
+      if (paramList->Parameters[i].Type == STATE) {
+         _mesa_fetch_state(ctx, paramList->Parameters[i].StateIndexes,
+                           paramList->Parameters[i].Values);
+      }
+   }
+}
+
+
+
+/**********************************************************************/
+/* API functions                                                      */
+/**********************************************************************/
+
+
+/**
+ * Bind a program (make it current)
+ * \note Called from the GL API dispatcher by both glBindProgramNV
+ * and glBindProgramARB.
+ */
+void
+_mesa_BindProgram(GLenum target, GLuint id)
+{
+   struct program *prog;
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if ((target == GL_VERTEX_PROGRAM_NV
+        && ctx->Extensions.NV_vertex_program) ||
+       (target == GL_VERTEX_PROGRAM_ARB
+        && ctx->Extensions.ARB_vertex_program)) {
+      if (ctx->VertexProgram.Current &&
+          ctx->VertexProgram.Current->Base.Id == id)
+         return;
+      /* decrement refcount on previously bound vertex program */
+      if (ctx->VertexProgram.Current) {
+         ctx->VertexProgram.Current->Base.RefCount--;
+         /* and delete if refcount goes below one */
+         if (ctx->VertexProgram.Current->Base.RefCount <= 0) {
+            _mesa_delete_program(ctx, &(ctx->VertexProgram.Current->Base));
+            _mesa_HashRemove(ctx->Shared->Programs, id);
+         }
+      }
+   }
+   else if ((target == GL_FRAGMENT_PROGRAM_NV
+             && ctx->Extensions.NV_fragment_program) ||
+            (target == GL_FRAGMENT_PROGRAM_ARB
+             && ctx->Extensions.ARB_fragment_program)) {
+      if (ctx->FragmentProgram.Current &&
+          ctx->FragmentProgram.Current->Base.Id == id)
+         return;
+      /* decrement refcount on previously bound fragment program */
+      if (ctx->FragmentProgram.Current) {
+         ctx->FragmentProgram.Current->Base.RefCount--;
+         /* and delete if refcount goes below one */
+         if (ctx->FragmentProgram.Current->Base.RefCount <= 0) {
+            _mesa_delete_program(ctx, &(ctx->FragmentProgram.Current->Base));
+            _mesa_HashRemove(ctx->Shared->Programs, id);
+         }
+      }
+   }
+   else {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glBindProgramNV/ARB(target)");
+      return;
+   }
+
+   /* NOTE: binding to a non-existant program is not an error.
+    * That's supposed to be caught in glBegin.
+    */
+   if (id == 0) {
+      /* default program */
+      prog = NULL;
+      if (target == GL_VERTEX_PROGRAM_NV || target == GL_VERTEX_PROGRAM_ARB)
+         prog = ctx->Shared->DefaultVertexProgram;
+      else
+         prog = ctx->Shared->DefaultFragmentProgram;
+   }
+   else {
+      prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, id);
+      if (prog) {
+         if (prog->Target == 0) {
+            /* prog was allocated with glGenProgramsNV */
+            prog->Target = target;
+         }
+         else if (prog->Target != target) {
+            _mesa_error(ctx, GL_INVALID_OPERATION,
+                        "glBindProgramNV/ARB(target mismatch)");
+            return;
+         }
+      }
+      else {
+         /* allocate a new program now */
+         prog = _mesa_alloc_program(ctx, target, id);
+         if (!prog) {
+            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindProgramNV/ARB");
+            return;
+         }
+         prog->Id = id;
+         prog->Target = target;
+         prog->Resident = GL_TRUE;
+         prog->RefCount = 1;
+         _mesa_HashInsert(ctx->Shared->Programs, id, prog);
+      }
+   }
+
+   /* bind now */
+   if (target == GL_VERTEX_PROGRAM_NV || target == GL_VERTEX_PROGRAM_ARB) {
+      ctx->VertexProgram.Current = (struct vertex_program *) prog;
+   }
+   else if (target == GL_FRAGMENT_PROGRAM_NV || target == GL_FRAGMENT_PROGRAM_ARB) {
+      ctx->FragmentProgram.Current = (struct fragment_program *) prog;
+   }
+
+   if (prog)
+      prog->RefCount++;
+}
+
+
+/**
+ * Delete a list of programs.
+ * \note Not compiled into display lists.
+ * \note Called by both glDeleteProgramsNV and glDeleteProgramsARB.
+ */
+void
+_mesa_DeletePrograms(GLsizei n, const GLuint *ids)
+{
+   GLint i;
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (n < 0) {
+      _mesa_error( ctx, GL_INVALID_VALUE, "glDeleteProgramsNV" );
+      return;
+   }
+
+   for (i = 0; i < n; i++) {
+      if (ids[i] != 0) {
+         struct program *prog = (struct program *)
+            _mesa_HashLookup(ctx->Shared->Programs, ids[i]);
+         if (prog) {
+            if (prog->Target == GL_VERTEX_PROGRAM_NV ||
+                prog->Target == GL_VERTEX_STATE_PROGRAM_NV) {
+               if (ctx->VertexProgram.Current &&
+                   ctx->VertexProgram.Current->Base.Id == ids[i]) {
+                  /* unbind this currently bound program */
+                  _mesa_BindProgram(prog->Target, 0);
+               }
+            }
+            else if (prog->Target == GL_FRAGMENT_PROGRAM_NV) {
+               if (ctx->FragmentProgram.Current &&
+                   ctx->FragmentProgram.Current->Base.Id == ids[i]) {
+                  /* unbind this currently bound program */
+                  _mesa_BindProgram(prog->Target, 0);
+               }
+            }
+            else {
+               _mesa_problem(ctx, "bad target in glDeleteProgramsNV");
+               return;
+            }
+            prog->RefCount--;
+            if (prog->RefCount <= 0) {
+               _mesa_delete_program(ctx, prog);
+            }
+         }
+      }
+   }
+}
+
+
+/**
+ * Generate a list of new program identifiers.
+ * \note Not compiled into display lists.
+ * \note Called by both glGenProgramsNV and glGenProgramsARB.
+ */
+void
+_mesa_GenPrograms(GLsizei n, GLuint *ids)
+{
+   GLuint first;
+   GLuint i;
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (n < 0) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "glGenPrograms");
+      return;
+   }
+
+   if (!ids)
+      return;
+
+   first = _mesa_HashFindFreeKeyBlock(ctx->Shared->Programs, n);
+
+   for (i = 0; i < (GLuint) n; i++) {
+      const int bytes = MAX2(sizeof(struct vertex_program),
+                             sizeof(struct fragment_program));
+      struct program *prog = (struct program *) _mesa_calloc(bytes);
+      if (!prog) {
+         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenPrograms");
+         return;
+      }
+      prog->RefCount = 1;
+      prog->Id = first + i;
+      _mesa_HashInsert(ctx->Shared->Programs, first + i, prog);
+   }
+
+   /* Return the program names */
+   for (i = 0; i < (GLuint) n; i++) {
+      ids[i] = first + i;
+   }
+}
+
+
+/**
+ * Determine if id names a program.
+ * \note Not compiled into display lists.
+ * \note Called from both glIsProgramNV and glIsProgramARB.
+ * \param id is the program identifier
+ * \return GL_TRUE if id is a program, else GL_FALSE.
+ */
+GLboolean
+_mesa_IsProgram(GLuint id)
+{
+   struct program *prog;
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
+
+   if (id == 0)
+      return GL_FALSE;
+
+   prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, id);
+   if (prog && prog->Target)
+      return GL_TRUE;
+   else
+      return GL_FALSE;
+}
diff --git a/src/mesa/main/program.h b/src/mesa/main/program.h
new file mode 100644 (file)
index 0000000..02d962c
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  5.1
+ *
+ * Copyright (C) 1999-2003  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 program.c
+ * Vertex and fragment program support functions.
+ * \author Brian Paul
+ */
+
+
+#ifndef PROGRAM_H
+#define PROGRAM_H
+
+#include "mtypes.h"
+
+
+
+/*
+ * Internal functions
+ */
+
+extern void
+_mesa_init_program(GLcontext *ctx);
+
+extern void
+_mesa_set_program_error(GLcontext *ctx, GLint pos, const char *string);
+
+extern const GLubyte *
+_mesa_find_line_column(const GLubyte *string, const GLubyte *pos,
+                       GLint *line, GLint *col);
+
+extern struct program *
+_mesa_alloc_program(GLcontext *ctx, GLenum target, GLuint id);
+
+extern void
+_mesa_delete_program(GLcontext *ctx, struct program *prog);
+
+
+
+/*
+ * 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 ].
+ */
+enum state_index {
+   STATE_MATERIAL,
+
+   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_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
+};
+
+
+
+/*
+ * 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.
+ */
+
+enum parameter_type
+{
+   NAMED_PARAMETER,
+   CONSTANT,
+   STATE
+};
+
+
+struct program_parameter
+{
+   const char *Name;                   /* Null-terminated */
+   enum parameter_type Type;
+   enum state_index StateIndexes[5];   /* Global state reference */
+   GLfloat Values[4];
+};
+
+
+struct program_parameter_list
+{
+   GLuint NumParameters;
+   struct program_parameter *Parameters;
+};
+
+
+/*
+ * Program parameter functions
+ */
+
+extern struct program_parameter_list *
+_mesa_new_parameter_list(void);
+
+extern void
+_mesa_free_parameter_list(struct program_parameter_list *paramList);
+
+extern void
+_mesa_free_parameters(struct program_parameter_list *paramList);
+
+extern GLint
+_mesa_add_named_parameter(struct program_parameter_list *paramList,
+                          const char *name, const GLfloat values[4]);
+
+extern GLint
+_mesa_add_named_constant(struct program_parameter_list *paramList,
+                         const char *name, const GLfloat values[4]);
+
+extern GLint
+_mesa_add_unnamed_constant(struct program_parameter_list *paramList,
+                           const GLfloat values[4]);
+
+extern GLint
+_mesa_add_state_reference(struct program_parameter_list *paramList,
+                          const char *stateString);
+
+extern GLfloat *
+_mesa_lookup_parameter_value(struct program_parameter_list *paramList,
+                             GLsizei nameLen, const char *name);
+
+extern GLint
+_mesa_lookup_parameter_index(struct program_parameter_list *paramList,
+                             GLsizei nameLen, const char *name);
+
+extern void
+_mesa_load_state_parameters(GLcontext *ctx,
+                            struct program_parameter_list *paramList);
+
+
+/*
+ * API functions
+ */
+
+extern void
+_mesa_BindProgram(GLenum target, GLuint id);
+
+extern void
+_mesa_DeletePrograms(GLsizei n, const GLuint *ids);
+
+extern void
+_mesa_GenPrograms(GLsizei n, GLuint *ids);
+
+extern GLboolean
+_mesa_IsProgram(GLuint id);
+
+
+#endif /* PROGRAM_H */
index 7b53519..2922828 100644 (file)
 #include "texstate.h"
 #include "mtypes.h"
 #include "varray.h"
-#if FEATURE_NV_vertex_program || FEATURE_NV_fragment_program
+#if FEATURE_NV_vertex_program
 #include "nvprogram.h"
 #endif
 #if FEATURE_NV_fragment_program
 #include "nvfragprog.h"
+#include "nvprogram.h"
+#include "program.h"
 #endif
 #include "debug.h"
 
@@ -544,10 +546,10 @@ _mesa_init_exec_table(struct _glapi_table *exec, GLuint tableSize)
 
    /* 233. GL_NV_vertex_program */
 #if FEATURE_NV_vertex_program
-   exec->BindProgramNV = _mesa_BindProgramNV;
-   exec->DeleteProgramsNV = _mesa_DeleteProgramsNV;
+   exec->BindProgramNV = _mesa_BindProgram;
+   exec->DeleteProgramsNV = _mesa_DeletePrograms;
    exec->ExecuteProgramNV = _mesa_ExecuteProgramNV;
-   exec->GenProgramsNV = _mesa_GenProgramsNV;
+   exec->GenProgramsNV = _mesa_GenPrograms;
    exec->AreProgramsResidentNV = _mesa_AreProgramsResidentNV;
    exec->RequestResidentProgramsNV = _mesa_RequestResidentProgramsNV;
    exec->GetProgramParameterfvNV = _mesa_GetProgramParameterfvNV;
@@ -559,7 +561,7 @@ _mesa_init_exec_table(struct _glapi_table *exec, GLuint tableSize)
    exec->GetVertexAttribfvNV = _mesa_GetVertexAttribfvNV;
    exec->GetVertexAttribivNV = _mesa_GetVertexAttribivNV;
    exec->GetVertexAttribPointervNV = _mesa_GetVertexAttribPointervNV;
-   exec->IsProgramNV = _mesa_IsProgramNV;
+   exec->IsProgramNV = _mesa_IsProgram;
    exec->LoadProgramNV = _mesa_LoadProgramNV;
    exec->ProgramParameter4dNV = _mesa_ProgramParameter4dNV;
    exec->ProgramParameter4dvNV = _mesa_ProgramParameter4dvNV;