diff options
| -rw-r--r-- | src/mesa/main/Makefile.X11 | 1 | ||||
| -rw-r--r-- | src/mesa/main/arbfragparse.h | 2 | ||||
| -rw-r--r-- | src/mesa/main/arbprogram.c | 34 | ||||
| -rw-r--r-- | src/mesa/main/arbprogram.h | 5 | ||||
| -rw-r--r-- | src/mesa/main/context.c | 5 | ||||
| -rw-r--r-- | src/mesa/main/descrip.mms | 3 | ||||
| -rw-r--r-- | src/mesa/main/dlist.c | 8 | ||||
| -rw-r--r-- | src/mesa/main/main.dsp | 8 | ||||
| -rw-r--r-- | src/mesa/main/mtypes.h | 14 | ||||
| -rw-r--r-- | src/mesa/main/nvfragparse.c | 127 | ||||
| -rw-r--r-- | src/mesa/main/nvfragprog.h | 2 | ||||
| -rw-r--r-- | src/mesa/main/nvprogram.c | 396 | ||||
| -rw-r--r-- | src/mesa/main/nvprogram.h | 57 | ||||
| -rw-r--r-- | src/mesa/main/nvvertparse.c | 2 | ||||
| -rw-r--r-- | src/mesa/main/nvvertprog.h | 2 | ||||
| -rw-r--r-- | src/mesa/main/program.c | 927 | ||||
| -rw-r--r-- | src/mesa/main/program.h | 207 | ||||
| -rw-r--r-- | src/mesa/main/state.c | 12 | 
18 files changed, 1216 insertions, 596 deletions
| diff --git a/src/mesa/main/Makefile.X11 b/src/mesa/main/Makefile.X11 index d918656c14..1f9bd666d5 100644 --- a/src/mesa/main/Makefile.X11 +++ b/src/mesa/main/Makefile.X11 @@ -62,6 +62,7 @@ CORE_SOURCES = \  	pixel.c \  	points.c \  	polygon.c \ +	program.c \  	rastpos.c \  	state.c \  	stencil.c \ diff --git a/src/mesa/main/arbfragparse.h b/src/mesa/main/arbfragparse.h index ad6d8efe4a..17e8dcf623 100644 --- a/src/mesa/main/arbfragparse.h +++ b/src/mesa/main/arbfragparse.h @@ -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, diff --git a/src/mesa/main/arbprogram.c b/src/mesa/main/arbprogram.c index 07ba462219..4e40d27834 100644 --- a/src/mesa/main/arbprogram.c +++ b/src/mesa/main/arbprogram.c @@ -44,40 +44,6 @@  #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)  { diff --git a/src/mesa/main/arbprogram.h b/src/mesa/main/arbprogram.h index 07cd3a17aa..bc5a6626ed 100644 --- a/src/mesa/main/arbprogram.h +++ b/src/mesa/main/arbprogram.h @@ -26,11 +26,6 @@  #ifndef ARBPROGRAM_H  #define ARBPROGRAM_H -#include "mtypes.h" - -extern void -_mesa_init_program(GLcontext *ctx); -  extern void  _mesa_EnableVertexAttribArrayARB(GLuint index); diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c index 8e5884a6cb..9151c74899 100644 --- a/src/mesa/main/context.c +++ b/src/mesa/main/context.c @@ -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" @@ -111,8 +110,8 @@  #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 diff --git a/src/mesa/main/descrip.mms b/src/mesa/main/descrip.mms index 9cff58e8ff..41b5fe52e2 100644 --- a/src/mesa/main/descrip.mms +++ b/src/mesa/main/descrip.mms @@ -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 diff --git a/src/mesa/main/dlist.c b/src/mesa/main/dlist.c index abfc2dfff8..36809fbe57 100644 --- a/src/mesa/main/dlist.c +++ b/src/mesa/main/dlist.c @@ -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; diff --git a/src/mesa/main/main.dsp b/src/mesa/main/main.dsp index 72d7edd5cb..9f1537fd53 100644 --- a/src/mesa/main/main.dsp +++ b/src/mesa/main/main.dsp @@ -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 diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 5497aac838..47cb19b625 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -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] */  }; diff --git a/src/mesa/main/nvfragparse.c b/src/mesa/main/nvfragparse.c index 36840d0e75..cf631a5e18 100644 --- a/src/mesa/main/nvfragparse.c +++ b/src/mesa/main/nvfragparse.c @@ -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) { diff --git a/src/mesa/main/nvfragprog.h b/src/mesa/main/nvfragprog.h index 33b219c4ce..cf5253b245 100644 --- a/src/mesa/main/nvfragprog.h +++ b/src/mesa/main/nvfragprog.h @@ -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.   */ diff --git a/src/mesa/main/nvprogram.c b/src/mesa/main/nvprogram.c index 61dca5001a..a4af0eb80a 100644 --- a/src/mesa/main/nvprogram.c +++ b/src/mesa/main/nvprogram.c @@ -41,294 +41,9 @@  #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"); diff --git a/src/mesa/main/nvprogram.h b/src/mesa/main/nvprogram.h index c9b8a838d9..f505a84ab8 100644 --- a/src/mesa/main/nvprogram.h +++ b/src/mesa/main/nvprogram.h @@ -30,36 +30,9 @@  #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 diff --git a/src/mesa/main/nvvertparse.c b/src/mesa/main/nvvertparse.c index fd99a261f0..50316b3692 100644 --- a/src/mesa/main/nvvertparse.c +++ b/src/mesa/main/nvvertparse.c @@ -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 diff --git a/src/mesa/main/nvvertprog.h b/src/mesa/main/nvvertprog.h index 1011fc5ad2..0dbee780df 100644 --- a/src/mesa/main/nvvertprog.h +++ b/src/mesa/main/nvvertprog.h @@ -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 index 0000000000..07ab420bcf --- /dev/null +++ b/src/mesa/main/program.c @@ -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 index 0000000000..02d962c796 --- /dev/null +++ b/src/mesa/main/program.h @@ -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 */ diff --git a/src/mesa/main/state.c b/src/mesa/main/state.c index 7b53519371..2922828d22 100644 --- a/src/mesa/main/state.c +++ b/src/mesa/main/state.c @@ -75,11 +75,13 @@  #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; | 
