aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Paul <[email protected]>2003-08-31 18:52:47 +0000
committerBrian Paul <[email protected]>2003-08-31 18:52:47 +0000
commit04a81da03bef5020d863e46aa597eddf7aaac016 (patch)
tree714f54ed6a4a5b74a17194cce98047e6a60dca1a
parente38a55ecb27562a52d48bf1d673803a10d8a5bce (diff)
Moved some shared vertex/fragment program code into new program.c file.
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.
-rw-r--r--src/mesa/main/Makefile.X111
-rw-r--r--src/mesa/main/arbfragparse.h2
-rw-r--r--src/mesa/main/arbprogram.c34
-rw-r--r--src/mesa/main/arbprogram.h5
-rw-r--r--src/mesa/main/context.c5
-rw-r--r--src/mesa/main/descrip.mms3
-rw-r--r--src/mesa/main/dlist.c8
-rw-r--r--src/mesa/main/main.dsp8
-rw-r--r--src/mesa/main/mtypes.h14
-rw-r--r--src/mesa/main/nvfragparse.c127
-rw-r--r--src/mesa/main/nvfragprog.h2
-rw-r--r--src/mesa/main/nvprogram.c396
-rw-r--r--src/mesa/main/nvprogram.h57
-rw-r--r--src/mesa/main/nvvertparse.c2
-rw-r--r--src/mesa/main/nvvertprog.h2
-rw-r--r--src/mesa/main/program.c927
-rw-r--r--src/mesa/main/program.h207
-rw-r--r--src/mesa/main/state.c12
18 files changed, 1216 insertions, 596 deletions
diff --git a/src/mesa/main/Makefile.X11 b/src/mesa/main/Makefile.X11
index d918656c146..1f9bd666d5d 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 ad6d8efe4a4..17e8dcf6239 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 07ba4622197..4e40d278343 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 07cd3a17aa1..bc5a6626ed5 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 8e5884a6cb9..9151c74899f 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 9cff58e8ffc..41b5fe52e2b 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 abfc2dfff88..36809fbe578 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 72d7edd5cb7..9f1537fd53d 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 5497aac8380..47cb19b6259 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 36840d0e753..cf631a5e184 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 33b219c4ce1..cf5253b2457 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 61dca5001ac..a4af0eb80a3 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 c9b8a838d94..f505a84ab8c 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 fd99a261f0b..50316b3692f 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 1011fc5ad2d..0dbee780dfd 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 00000000000..07ab420bcf7
--- /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 00000000000..02d962c7965
--- /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 7b535193717..2922828d22b 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;