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.
This commit is contained in:
parent
e38a55ecb2
commit
04a81da03b
|
@ -62,6 +62,7 @@ CORE_SOURCES = \
|
|||
pixel.c \
|
||||
points.c \
|
||||
polygon.c \
|
||||
program.c \
|
||||
rastpos.c \
|
||||
state.c \
|
||||
stencil.c \
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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] */
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
@ -361,49 +76,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.
|
||||
|
@ -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");
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue