X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fmain%2Fnvprogram.c;h=dd198b8141ab76108039181758f777d31388f8cc;hb=cf143c1f4d7c3636ddd5c767518b1b00ff46b16c;hp=75518350b314775f0059e5decb6804470dc816c2;hpb=451566305287161d51eb5643a5fd398809ac03c1;p=mesa.git diff --git a/src/mesa/main/nvprogram.c b/src/mesa/main/nvprogram.c index 75518350b31..dd198b8141a 100644 --- a/src/mesa/main/nvprogram.c +++ b/src/mesa/main/nvprogram.c @@ -1,10 +1,8 @@ -/* $Id: nvprogram.c,v 1.9 2003/03/19 05:34:25 brianp Exp $ */ - /* * Mesa 3-D graphics library - * Version: 5.1 + * Version: 6.5.2 * - * Copyright (C) 1999-2003 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -26,275 +24,43 @@ /** * \file nvprogram.c - * \brief NVIDIA vertex/fragment program state management functions. + * NVIDIA vertex/fragment program state management functions. * \author Brian Paul */ - -#include "glheader.h" -#include "context.h" -#include "hash.h" -#include "imports.h" -#include "macros.h" -#include "mtypes.h" -#include "nvfragparse.h" -#include "nvfragprog.h" -#include "nvvertexec.h" -#include "nvvertparse.h" -#include "nvvertprog.h" -#include "nvprogram.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; -} - - - - -/** - * 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, GLuint id) -{ - struct program *prog = (struct program *) - _mesa_HashLookup(ctx->Shared->Programs, id); - - if (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_HashRemove(ctx->Shared->Programs, id); - _mesa_free(prog); - } -} - - -/** - * Bind a program (make it current) - * \note Called from the GL API dispatcher. - */ -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) { - 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.Id); - } - } - else if (target == GL_FRAGMENT_PROGRAM_NV) { - 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.Id); - } - } - else { - _mesa_error(ctx, GL_INVALID_ENUM, "glBindProgramNV"); - return; - } - - /* NOTE: binding to a non-existant program is not an error. - * That's supposed to be caught in glBegin. - */ - if (id == 0) { - /* OK, the null program object */ - prog = NULL; - } - else { - prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, id); - - if (!prog && id > 0){ - /* allocate new program */ - if (target == GL_VERTEX_PROGRAM_NV) { - struct vertex_program *vprog = CALLOC_STRUCT(vertex_program); - if (!vprog) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindProgramNV"); - return; - } - prog = &(vprog->Base); - } - else if (target == GL_FRAGMENT_PROGRAM_NV) { - struct fragment_program *fprog = CALLOC_STRUCT(fragment_program); - if (!fprog) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindProgramNV"); - return; - } - prog = &(fprog->Base); - } - else { - _mesa_error(ctx, GL_INVALID_ENUM, "glBindProgramNV(target)"); - 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) { - ctx->VertexProgram.Current = (struct vertex_program *) prog; - } - else if (target == GL_FRAGMENT_PROGRAM_NV) { - ctx->FragmentProgram.Current = (struct fragment_program *) prog; - } - - if (prog) - prog->RefCount++; -} - - -/** - * Delete a list of programs. - * \note Not compiled into display lists. - * \note Called from the GL API dispatcher. +/* + * Regarding GL_NV_fragment/vertex_program, GL_NV_vertex_program1_1, etc: + * + * Portions of this software may use or implement intellectual + * property owned and licensed by NVIDIA Corporation. NVIDIA disclaims + * any and all warranties with respect to such intellectual property, + * including any use thereof or modifications thereto. */ -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; - } +#include "main/glheader.h" +#include "main/context.h" +#include "main/hash.h" +#include "main/imports.h" +#include "main/macros.h" +#include "main/mtypes.h" +#include "main/nvprogram.h" +#include "program/arbprogparse.h" +#include "program/nvfragparse.h" +#include "program/nvvertparse.h" +#include "program/program.h" +#include "program/prog_instruction.h" +#include "program/prog_parameter.h" - 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, ids[i]); - } - } - } - } -} /** * Execute a vertex state program. * \note Called from the GL API dispatcher. */ -void +void GLAPIENTRY _mesa_ExecuteProgramNV(GLenum target, GLuint id, const GLfloat *params) { - struct vertex_program *vprog; + struct gl_vertex_program *vprog; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); @@ -303,61 +69,16 @@ _mesa_ExecuteProgramNV(GLenum target, GLuint id, const GLfloat *params) return; } - vprog = (struct vertex_program *) - _mesa_HashLookup(ctx->Shared->Programs, id); + FLUSH_VERTICES(ctx, _NEW_PROGRAM); + + vprog = (struct gl_vertex_program *) _mesa_lookup_program(ctx, id); if (!vprog || vprog->Base.Target != GL_VERTEX_STATE_PROGRAM_NV) { _mesa_error(ctx, GL_INVALID_OPERATION, "glExecuteProgramNV"); return; } - _mesa_init_vp_registers(ctx); - _mesa_init_tracked_matrices(ctx); - COPY_4V(ctx->VertexProgram.Machine.Registers[VP_INPUT_REG_START], params); - _mesa_exec_vertex_program(ctx, vprog); -} - - -/** - * Generate a list of new program identifiers. - * \note Not compiled into display lists. - * \note Called from the GL API dispatcher. - */ -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, "glGenProgramsNV"); - 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, "glGenProgramsNV"); - 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; - } + _mesa_problem(ctx, "glExecuteProgramNV() not supported"); } @@ -366,8 +87,9 @@ _mesa_GenProgramsNV(GLsizei n, GLuint *ids) * \note Not compiled into display lists. * \note Called from the GL API dispatcher. */ -GLboolean _mesa_AreProgramsResidentNV(GLsizei n, const GLuint *ids, - GLboolean *residences) +GLboolean GLAPIENTRY +_mesa_AreProgramsResidentNV(GLsizei n, const GLuint *ids, + GLboolean *residences) { GLint i, j; GLboolean allResident = GL_TRUE; @@ -380,13 +102,12 @@ GLboolean _mesa_AreProgramsResidentNV(GLsizei n, const GLuint *ids, } for (i = 0; i < n; i++) { - const struct program *prog; + const struct gl_program *prog; if (ids[i] == 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV"); return GL_FALSE; } - prog = (const struct program *) - _mesa_HashLookup(ctx->Shared->Programs, ids[i]); + prog = _mesa_lookup_program(ctx, ids[i]); if (!prog) { _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV"); return GL_FALSE; @@ -413,7 +134,7 @@ GLboolean _mesa_AreProgramsResidentNV(GLsizei n, const GLuint *ids, * Request that a set of programs be resident in hardware. * \note Called from the GL API dispatcher. */ -void +void GLAPIENTRY _mesa_RequestResidentProgramsNV(GLsizei n, const GLuint *ids) { GLint i; @@ -427,20 +148,20 @@ _mesa_RequestResidentProgramsNV(GLsizei n, const GLuint *ids) /* just error checking for now */ for (i = 0; i < n; i++) { - struct program *prog; + struct gl_program *prog; if (ids[i] == 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(id)"); return; } - prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, ids[i]); - + prog = _mesa_lookup_program(ctx, ids[i]); if (!prog) { _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(id)"); return; } + /* XXX this is really a hardware thing we should hook out */ prog->Resident = GL_TRUE; } } @@ -451,7 +172,7 @@ _mesa_RequestResidentProgramsNV(GLsizei n, const GLuint *ids) * \note Not compiled into display lists. * \note Called from the GL API dispatcher. */ -void +void GLAPIENTRY _mesa_GetProgramParameterfvNV(GLenum target, GLuint index, GLenum pname, GLfloat *params) { @@ -461,8 +182,7 @@ _mesa_GetProgramParameterfvNV(GLenum target, GLuint index, if (target == GL_VERTEX_PROGRAM_NV) { if (pname == GL_PROGRAM_PARAMETER_NV) { if (index < MAX_NV_VERTEX_PROGRAM_PARAMS) { - index += VP_PROG_REG_START; - COPY_4V(params, ctx->VertexProgram.Machine.Registers[index]); + COPY_4V(params, ctx->VertexProgram.Parameters[index]); } else { _mesa_error(ctx, GL_INVALID_VALUE, @@ -487,7 +207,7 @@ _mesa_GetProgramParameterfvNV(GLenum target, GLuint index, * \note Not compiled into display lists. * \note Called from the GL API dispatcher. */ -void +void GLAPIENTRY _mesa_GetProgramParameterdvNV(GLenum target, GLuint index, GLenum pname, GLdouble *params) { @@ -497,8 +217,7 @@ _mesa_GetProgramParameterdvNV(GLenum target, GLuint index, if (target == GL_VERTEX_PROGRAM_NV) { if (pname == GL_PROGRAM_PARAMETER_NV) { if (index < MAX_NV_VERTEX_PROGRAM_PARAMS) { - index += VP_PROG_REG_START; - COPY_4V(params, ctx->VertexProgram.Machine.Registers[index]); + COPY_4V(params, ctx->VertexProgram.Parameters[index]); } else { _mesa_error(ctx, GL_INVALID_VALUE, @@ -523,14 +242,15 @@ _mesa_GetProgramParameterdvNV(GLenum target, GLuint index, * \note Not compiled into display lists. * \note Called from the GL API dispatcher. */ -void +void GLAPIENTRY _mesa_GetProgramivNV(GLuint id, GLenum pname, GLint *params) { - struct program *prog; + struct gl_program *prog; GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); - prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, id); + prog = _mesa_lookup_program(ctx, id); if (!prog) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramivNV"); return; @@ -541,7 +261,7 @@ _mesa_GetProgramivNV(GLuint id, GLenum pname, GLint *params) *params = prog->Target; return; case GL_PROGRAM_LENGTH_NV: - *params = prog->String ? _mesa_strlen((char *) prog->String) : 0; + *params = prog->String ?(GLint) strlen((char *) prog->String) : 0; return; case GL_PROGRAM_RESIDENT_NV: *params = prog->Resident; @@ -558,26 +278,27 @@ _mesa_GetProgramivNV(GLuint id, GLenum pname, GLint *params) * \note Not compiled into display lists. * \note Called from the GL API dispatcher. */ -void +void GLAPIENTRY _mesa_GetProgramStringNV(GLuint id, GLenum pname, GLubyte *program) { - struct program *prog; + struct gl_program *prog; GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); if (pname != GL_PROGRAM_STRING_NV) { - _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivNV(pname)"); + _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringNV(pname)"); return; } - prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, id); + prog = _mesa_lookup_program(ctx, id); if (!prog) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramivNV"); + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramStringNV"); return; } if (prog->String) { - MEMCPY(program, prog->String, _mesa_strlen((char *) prog->String)); + memcpy(program, prog->String, strlen((char *) prog->String)); } else { program[0] = 0; @@ -590,14 +311,15 @@ _mesa_GetProgramStringNV(GLuint id, GLenum pname, GLubyte *program) * \note Not compiled into display lists. * \note Called from the GL API dispatcher. */ -void +void GLAPIENTRY _mesa_GetTrackMatrixivNV(GLenum target, GLuint address, GLenum pname, GLint *params) { GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); - if (target == GL_VERTEX_PROGRAM_NV) { + if (target == GL_VERTEX_PROGRAM_NV + && ctx->Extensions.NV_vertex_program) { GLuint i; if ((address & 0x3) || address >= MAX_NV_VERTEX_PROGRAM_PARAMS) { @@ -631,28 +353,37 @@ _mesa_GetTrackMatrixivNV(GLenum target, GLuint address, * \note Not compiled into display lists. * \note Called from the GL API dispatcher. */ -void +void GLAPIENTRY _mesa_GetVertexAttribdvNV(GLuint index, GLenum pname, GLdouble *params) { + const struct gl_client_array *array; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); - if (index == 0 || index >= VP_NUM_INPUT_REGS) { + if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)"); return; } + array = &ctx->Array.ArrayObj->VertexAttrib[index]; + switch (pname) { case GL_ATTRIB_ARRAY_SIZE_NV: - params[0] = ctx->Array.VertexAttrib[index].Size; + params[0] = array->Size; break; case GL_ATTRIB_ARRAY_STRIDE_NV: - params[0] = ctx->Array.VertexAttrib[index].Stride; + params[0] = array->Stride; break; case GL_ATTRIB_ARRAY_TYPE_NV: - params[0] = ctx->Array.VertexAttrib[index].Type; + params[0] = array->Type; break; case GL_CURRENT_ATTRIB_NV: + if (index == 0) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetVertexAttribdvNV(index == 0)"); + return; + } + FLUSH_CURRENT(ctx, 0); COPY_4V(params, ctx->Current.Attrib[index]); break; default: @@ -666,28 +397,37 @@ _mesa_GetVertexAttribdvNV(GLuint index, GLenum pname, GLdouble *params) * \note Not compiled into display lists. * \note Called from the GL API dispatcher. */ -void +void GLAPIENTRY _mesa_GetVertexAttribfvNV(GLuint index, GLenum pname, GLfloat *params) { + const struct gl_client_array *array; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); - if (index == 0 || index >= VP_NUM_INPUT_REGS) { + if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)"); return; } + array = &ctx->Array.ArrayObj->VertexAttrib[index]; + switch (pname) { case GL_ATTRIB_ARRAY_SIZE_NV: - params[0] = (GLfloat) ctx->Array.VertexAttrib[index].Size; + params[0] = (GLfloat) array->Size; break; case GL_ATTRIB_ARRAY_STRIDE_NV: - params[0] = (GLfloat) ctx->Array.VertexAttrib[index].Stride; + params[0] = (GLfloat) array->Stride; break; case GL_ATTRIB_ARRAY_TYPE_NV: - params[0] = (GLfloat) ctx->Array.VertexAttrib[index].Type; + params[0] = (GLfloat) array->Type; break; case GL_CURRENT_ATTRIB_NV: + if (index == 0) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetVertexAttribfvNV(index == 0)"); + return; + } + FLUSH_CURRENT(ctx, 0); COPY_4V(params, ctx->Current.Attrib[index]); break; default: @@ -701,29 +441,44 @@ _mesa_GetVertexAttribfvNV(GLuint index, GLenum pname, GLfloat *params) * \note Not compiled into display lists. * \note Called from the GL API dispatcher. */ -void +void GLAPIENTRY _mesa_GetVertexAttribivNV(GLuint index, GLenum pname, GLint *params) { + const struct gl_client_array *array; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); - if (index == 0 || index >= VP_NUM_INPUT_REGS) { + if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)"); return; } + array = &ctx->Array.ArrayObj->VertexAttrib[index]; + switch (pname) { case GL_ATTRIB_ARRAY_SIZE_NV: - params[0] = ctx->Array.VertexAttrib[index].Size; + params[0] = array->Size; break; case GL_ATTRIB_ARRAY_STRIDE_NV: - params[0] = ctx->Array.VertexAttrib[index].Stride; + params[0] = array->Stride; break; case GL_ATTRIB_ARRAY_TYPE_NV: - params[0] = ctx->Array.VertexAttrib[index].Type; + params[0] = array->Type; break; case GL_CURRENT_ATTRIB_NV: - COPY_4V_CAST(params, ctx->Current.Attrib[index], GLint); + if (index == 0) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetVertexAttribivNV(index == 0)"); + return; + } + FLUSH_CURRENT(ctx, 0); + params[0] = (GLint) ctx->Current.Attrib[index][0]; + params[1] = (GLint) ctx->Current.Attrib[index][1]; + params[2] = (GLint) ctx->Current.Attrib[index][2]; + params[3] = (GLint) ctx->Current.Attrib[index][3]; + break; + case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB: + params[0] = array->BufferObj->Name; break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV"); @@ -737,7 +492,7 @@ _mesa_GetVertexAttribivNV(GLuint index, GLenum pname, GLint *params) * \note Not compiled into display lists. * \note Called from the GL API dispatcher. */ -void +void GLAPIENTRY _mesa_GetVertexAttribPointervNV(GLuint index, GLenum pname, GLvoid **pointer) { GET_CURRENT_CONTEXT(ctx); @@ -753,187 +508,200 @@ _mesa_GetVertexAttribPointervNV(GLuint index, GLenum pname, GLvoid **pointer) return; } - *pointer = ctx->Array.VertexAttrib[index].Ptr;; + *pointer = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[index].Ptr; } - -/** - * Determine if id names a program. - * \note Not compiled into display lists. - * \note Called from the GL API dispatcher. - * \param id is the program identifier - * \return GL_TRUE if id is a program, else GL_FALSE. - */ -GLboolean _mesa_IsProgramNV(GLuint id) +void +_mesa_emit_nv_temp_initialization(struct gl_context *ctx, + struct gl_program *program) { - struct program *prog; - GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); + struct prog_instruction *inst; + GLuint i; + struct gl_shader_compiler_options* options = + &ctx->ShaderCompilerOptions[_mesa_program_target_to_index(program->Target)]; - if (id == 0) - return GL_FALSE; + if (!options->EmitNVTempInitialization) + return; - prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, id); - if (prog && prog->Target) - return GL_TRUE; - else - return GL_FALSE; + /* We'll swizzle up a zero temporary so we can use it for the + * ARL. + */ + if (program->NumTemporaries == 0) + program->NumTemporaries = 1; + + _mesa_insert_instructions(program, 0, program->NumTemporaries + 1); + + for (i = 0; i < program->NumTemporaries; i++) { + struct prog_instruction *inst = &program->Instructions[i]; + + inst->Opcode = OPCODE_SWZ; + inst->DstReg.File = PROGRAM_TEMPORARY; + inst->DstReg.Index = i; + inst->DstReg.WriteMask = WRITEMASK_XYZW; + inst->SrcReg[0].File = PROGRAM_TEMPORARY; + inst->SrcReg[0].Index = 0; + inst->SrcReg[0].Swizzle = MAKE_SWIZZLE4(SWIZZLE_ZERO, + SWIZZLE_ZERO, + SWIZZLE_ZERO, + SWIZZLE_ZERO); + } + + inst = &program->Instructions[i]; + inst->Opcode = OPCODE_ARL; + inst->DstReg.File = PROGRAM_ADDRESS; + inst->DstReg.Index = 0; + inst->DstReg.WriteMask = WRITEMASK_XYZW; + inst->SrcReg[0].File = PROGRAM_TEMPORARY; + inst->SrcReg[0].Index = 0; + inst->SrcReg[0].Swizzle = SWIZZLE_XXXX; + + if (program->NumAddressRegs == 0) + program->NumAddressRegs = 1; } +void +_mesa_setup_nv_temporary_count(struct gl_context *ctx, struct gl_program *program) +{ + GLuint i; + + program->NumTemporaries = 0; + for (i = 0; i < program->NumInstructions; i++) { + struct prog_instruction *inst = &program->Instructions[i]; + + if (inst->DstReg.File == PROGRAM_TEMPORARY) { + program->NumTemporaries = MAX2(program->NumTemporaries, + inst->DstReg.Index + 1); + } + if (inst->SrcReg[0].File == PROGRAM_TEMPORARY) { + program->NumTemporaries = MAX2((GLint)program->NumTemporaries, + inst->SrcReg[0].Index + 1); + } + if (inst->SrcReg[1].File == PROGRAM_TEMPORARY) { + program->NumTemporaries = MAX2((GLint)program->NumTemporaries, + inst->SrcReg[1].Index + 1); + } + if (inst->SrcReg[2].File == PROGRAM_TEMPORARY) { + program->NumTemporaries = MAX2((GLint)program->NumTemporaries, + inst->SrcReg[2].Index + 1); + } + } +} /** - * Load a program. + * Load/parse/compile a program. * \note Called from the GL API dispatcher. */ -void +void GLAPIENTRY _mesa_LoadProgramNV(GLenum target, GLuint id, GLsizei len, const GLubyte *program) { - struct program *prog; + struct gl_program *prog; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (!ctx->Extensions.NV_vertex_program + && !ctx->Extensions.NV_fragment_program) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV()"); + return; + } + if (id == 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glLoadProgramNV(id)"); return; } - prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, id); + if (len < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glLoadProgramNV(len)"); + return; + } + + FLUSH_VERTICES(ctx, _NEW_PROGRAM); + + prog = _mesa_lookup_program(ctx, id); if (prog && prog->Target != 0 && prog->Target != target) { _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(target)"); return; } - /* Reset error pos and string */ - _mesa_set_program_error(ctx, -1, NULL); - - if (target == GL_VERTEX_PROGRAM_NV || - target == GL_VERTEX_STATE_PROGRAM_NV) { - struct vertex_program *vprog = (struct vertex_program *) prog; - if (!vprog) { - vprog = CALLOC_STRUCT(vertex_program); + if ((target == GL_VERTEX_PROGRAM_NV || + target == GL_VERTEX_STATE_PROGRAM_NV) + && ctx->Extensions.NV_vertex_program) { + struct gl_vertex_program *vprog = (struct gl_vertex_program *) prog; + if (!vprog || prog == &_mesa_DummyProgram) { + vprog = (struct gl_vertex_program *) + ctx->Driver.NewProgram(ctx, target, id); if (!vprog) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV"); return; } - vprog->Base.RefCount = 1; - vprog->Base.Resident = GL_TRUE; _mesa_HashInsert(ctx->Shared->Programs, id, vprog); } - _mesa_parse_nv_vertex_program(ctx, target, program, len, vprog); + + if (ctx->Extensions.ARB_vertex_program + && (strncmp((char *) program, "!!ARB", 5) == 0)) { + _mesa_parse_arb_vertex_program(ctx, target, program, len, vprog); + } else { + _mesa_parse_nv_vertex_program(ctx, target, program, len, vprog); + } } - else if (target == GL_FRAGMENT_PROGRAM_NV) { - struct fragment_program *fprog = (struct fragment_program *) prog; - if (!fprog) { - fprog = CALLOC_STRUCT(fragment_program); + else if (target == GL_FRAGMENT_PROGRAM_NV + && ctx->Extensions.NV_fragment_program) { + struct gl_fragment_program *fprog = (struct gl_fragment_program *) prog; + if (!fprog || prog == &_mesa_DummyProgram) { + fprog = (struct gl_fragment_program *) + ctx->Driver.NewProgram(ctx, target, id); if (!fprog) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV"); return; } - fprog->Base.RefCount = 1; - fprog->Base.Resident = GL_TRUE; _mesa_HashInsert(ctx->Shared->Programs, id, fprog); } _mesa_parse_nv_fragment_program(ctx, target, program, len, fprog); } - else { - _mesa_error(ctx, GL_INVALID_ENUM, "LoadProgramNV(target)"); - } -} - - - -/** - * Set a program parameter register. - * \note Called from the GL API dispatcher. - */ -void -_mesa_ProgramParameter4dNV(GLenum target, GLuint index, - GLdouble x, GLdouble y, GLdouble z, GLdouble w) -{ - _mesa_ProgramParameter4fNV(target, index, - (GLfloat)x, (GLfloat)y, (GLfloat)z, (GLfloat)w); -} - - -/** - * Set a program parameter register. - * \note Called from the GL API dispatcher. - */ -void -_mesa_ProgramParameter4dvNV(GLenum target, GLuint index, - const GLdouble *params) -{ - _mesa_ProgramParameter4fNV(target, index, - (GLfloat)params[0], (GLfloat)params[1], - (GLfloat)params[2], (GLfloat)params[3]); -} - - -/** - * Set a program parameter register. - * \note Called from the GL API dispatcher. - */ -void -_mesa_ProgramParameter4fNV(GLenum target, GLuint index, - GLfloat x, GLfloat y, GLfloat z, GLfloat w) -{ - GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END(ctx); - - if (target == GL_VERTEX_PROGRAM_NV) { - if (index < MAX_NV_VERTEX_PROGRAM_PARAMS) { - index += VP_PROG_REG_START; - ASSIGN_4V(ctx->VertexProgram.Machine.Registers[index], x, y, z, w); - } - else { - _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameterNV(index)"); - return; + else if (target == GL_FRAGMENT_PROGRAM_ARB + && ctx->Extensions.ARB_fragment_program) { + struct gl_fragment_program *fprog = (struct gl_fragment_program *) prog; + if (!fprog || prog == &_mesa_DummyProgram) { + fprog = (struct gl_fragment_program *) + ctx->Driver.NewProgram(ctx, target, id); + if (!fprog) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV"); + return; + } + _mesa_HashInsert(ctx->Shared->Programs, id, fprog); } + _mesa_parse_arb_fragment_program(ctx, target, program, len, fprog); } else { - _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameterNV"); - return; + _mesa_error(ctx, GL_INVALID_ENUM, "glLoadProgramNV(target)"); } } -/** - * Set a program parameter register. - * \note Called from the GL API dispatcher. - */ -void -_mesa_ProgramParameter4fvNV(GLenum target, GLuint index, - const GLfloat *params) -{ - _mesa_ProgramParameter4fNV(target, index, - params[0], params[1], params[2], params[3]); -} - - /** * Set a sequence of program parameter registers. * \note Called from the GL API dispatcher. */ -void +void GLAPIENTRY _mesa_ProgramParameters4dvNV(GLenum target, GLuint index, - GLuint num, const GLdouble *params) + GLsizei num, const GLdouble *params) { GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); - if (target == GL_VERTEX_PROGRAM_NV) { - GLuint i; + if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) { + GLint i; if (index + num > MAX_NV_VERTEX_PROGRAM_PARAMS) { _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameters4dvNV"); return; } - index += VP_PROG_REG_START; for (i = 0; i < num; i++) { - COPY_4V_CAST(ctx->VertexProgram.Machine.Registers[index + i], - params, GLfloat); + ctx->VertexProgram.Parameters[index + i][0] = (GLfloat) params[0]; + ctx->VertexProgram.Parameters[index + i][1] = (GLfloat) params[1]; + ctx->VertexProgram.Parameters[index + i][2] = (GLfloat) params[2]; + ctx->VertexProgram.Parameters[index + i][3] = (GLfloat) params[3]; params += 4; }; } @@ -948,24 +716,23 @@ _mesa_ProgramParameters4dvNV(GLenum target, GLuint index, * Set a sequence of program parameter registers. * \note Called from the GL API dispatcher. */ -void +void GLAPIENTRY _mesa_ProgramParameters4fvNV(GLenum target, GLuint index, - GLuint num, const GLfloat *params) + GLsizei num, const GLfloat *params) { GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); - if (target == GL_VERTEX_PROGRAM_NV) { - GLuint i; + if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) { + GLint i; if (index + num > MAX_NV_VERTEX_PROGRAM_PARAMS) { _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameters4fvNV"); return; } - index += VP_PROG_REG_START; for (i = 0; i < num; i++) { - COPY_4V(ctx->VertexProgram.Machine.Registers[index + i], params); + COPY_4V(ctx->VertexProgram.Parameters[index + i], params); params += 4; - }; + } } else { _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameters4fvNV"); @@ -979,14 +746,16 @@ _mesa_ProgramParameters4fvNV(GLenum target, GLuint index, * Setup tracking of matrices into program parameter registers. * \note Called from the GL API dispatcher. */ -void +void GLAPIENTRY _mesa_TrackMatrixNV(GLenum target, GLuint address, GLenum matrix, GLenum transform) { GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); - if (target == GL_VERTEX_PROGRAM_NV) { + FLUSH_VERTICES(ctx, _NEW_PROGRAM); + + if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) { if (address & 0x3) { /* addr must be multiple of four */ _mesa_error(ctx, GL_INVALID_VALUE, "glTrackMatrixNV(address)"); @@ -1037,79 +806,85 @@ _mesa_TrackMatrixNV(GLenum target, GLuint address, } -GLAPI void GLAPIENTRY -glProgramNamedParameter4fNV(GLuint id, GLsizei len, const GLubyte *name, - GLfloat x, GLfloat y, GLfloat z, GLfloat w) +void GLAPIENTRY +_mesa_ProgramNamedParameter4fNV(GLuint id, GLsizei len, const GLubyte *name, + GLfloat x, GLfloat y, GLfloat z, GLfloat w) { - struct program *prog; - struct fragment_program *fragProg; - GLint reg; + struct gl_program *prog; + struct gl_fragment_program *fragProg; + GLfloat *v; + GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); - prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, id); + FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS); + + prog = _mesa_lookup_program(ctx, id); if (!prog || prog->Target != GL_FRAGMENT_PROGRAM_NV) { _mesa_error(ctx, GL_INVALID_OPERATION, "glProgramNamedParameterNV"); return; } if (len <= 0) { - _mesa_error(ctx, GL_INVALID_VALUE, "glProgramNamedParameterNV"); + _mesa_error(ctx, GL_INVALID_VALUE, "glProgramNamedParameterNV(len)"); return; } - fragProg = (struct fragment_program *) prog; - for (reg = 0; reg < fragProg->NumParameters; reg++) { - if (!_mesa_strcmp(fragProg->Parameters[reg].Name, (const char *) name)) { - fragProg->Parameters[reg].Values[0] = x; - fragProg->Parameters[reg].Values[1] = y; - fragProg->Parameters[reg].Values[2] = z; - fragProg->Parameters[reg].Values[3] = w; - return; - } + fragProg = (struct gl_fragment_program *) prog; + v = _mesa_lookup_parameter_value(fragProg->Base.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"); + _mesa_error(ctx, GL_INVALID_VALUE, "glProgramNamedParameterNV(name)"); } -GLAPI void GLAPIENTRY -glProgramNamedParameter4fvNV(GLuint id, GLsizei len, const GLubyte *name, - const float v[]) +void GLAPIENTRY +_mesa_ProgramNamedParameter4fvNV(GLuint id, GLsizei len, const GLubyte *name, + const float v[]) { - glProgramNamedParameter4fNV(id, len, name, v[0], v[1], v[2], v[3]); + _mesa_ProgramNamedParameter4fNV(id, len, name, v[0], v[1], v[2], v[3]); } -GLAPI void GLAPIENTRY -glProgramNamedParameter4dNV(GLuint id, GLsizei len, const GLubyte *name, - GLdouble x, GLdouble y, GLdouble z, GLdouble w) +void GLAPIENTRY +_mesa_ProgramNamedParameter4dNV(GLuint id, GLsizei len, const GLubyte *name, + GLdouble x, GLdouble y, GLdouble z, GLdouble w) { - glProgramNamedParameter4fNV(id, len, name, (GLfloat)x, (GLfloat)y, - (GLfloat)z, (GLfloat)w); + _mesa_ProgramNamedParameter4fNV(id, len, name, (GLfloat)x, (GLfloat)y, + (GLfloat)z, (GLfloat)w); } -GLAPI void GLAPIENTRY -glProgramNamedParameter4dvNV(GLuint id, GLsizei len, const GLubyte *name, - const double v[]) +void GLAPIENTRY +_mesa_ProgramNamedParameter4dvNV(GLuint id, GLsizei len, const GLubyte *name, + const double v[]) { - glProgramNamedParameter4fNV(id, len, name, (GLfloat)v[0], (GLfloat)v[1], - (GLfloat)v[2], (GLfloat)v[3]); + _mesa_ProgramNamedParameter4fNV(id, len, name, + (GLfloat)v[0], (GLfloat)v[1], + (GLfloat)v[2], (GLfloat)v[3]); } -GLAPI void GLAPIENTRY -glGetProgramNamedParameterfvNV(GLuint id, GLsizei len, const GLubyte *name, - GLfloat *params) +void GLAPIENTRY +_mesa_GetProgramNamedParameterfvNV(GLuint id, GLsizei len, const GLubyte *name, + GLfloat *params) { - struct program *prog; - struct fragment_program *fragProg; - GLint reg; + struct gl_program *prog; + struct gl_fragment_program *fragProg; + const GLfloat *v; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); - prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, id); + prog = _mesa_lookup_program(ctx, id); if (!prog || prog->Target != GL_FRAGMENT_PROGRAM_NV) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramNamedParameterNV"); return; @@ -1120,120 +895,26 @@ glGetProgramNamedParameterfvNV(GLuint id, GLsizei len, const GLubyte *name, return; } - fragProg = (struct fragment_program *) prog; - for (reg = 0; reg < fragProg->NumParameters; reg++) { - if (!_mesa_strcmp(fragProg->Parameters[reg].Name, (const char *) name)) { - params[0] = fragProg->Parameters[reg].Values[0]; - params[1] = fragProg->Parameters[reg].Values[1]; - params[2] = fragProg->Parameters[reg].Values[2]; - params[3] = fragProg->Parameters[reg].Values[3]; - return; - } - } - - _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramNamedParameterNV"); -} - - -GLAPI void GLAPIENTRY -glGetProgramNamedParameterdvNV(GLuint id, GLsizei len, const GLubyte *name, - GLdouble *params) -{ - GLfloat floatParams[4]; - glGetProgramNamedParameterfvNV(id, len, name, floatParams); - COPY_4V(params, floatParams); -} - - -GLAPI void GLAPIENTRY -glProgramLocalParameter4fARB(GLenum target, GLuint index, - GLfloat x, GLfloat y, GLfloat z, GLfloat w) -{ - GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END(ctx); - - if (target == GL_FRAGMENT_PROGRAM_NV) { - struct fragment_program *fprog = ctx->FragmentProgram.Current; - if (!fprog) { - _mesa_error(ctx, GL_INVALID_ENUM, "glProgramLocalParameterARB"); - return; - } - if (index >= MAX_NV_FRAGMENT_PROGRAM_PARAMS) { - _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameterARB"); - return; - } - fprog->LocalParams[index][0] = x; - fprog->LocalParams[index][1] = y; - fprog->LocalParams[index][2] = z; - fprog->LocalParams[index][3] = w; - } - else { - _mesa_error(ctx, GL_INVALID_ENUM, "glProgramLocalParameterARB"); + fragProg = (struct gl_fragment_program *) prog; + v = _mesa_lookup_parameter_value(fragProg->Base.Parameters, + len, (char *) name); + if (v) { + params[0] = v[0]; + params[1] = v[1]; + params[2] = v[2]; + params[3] = v[3]; return; } -} - - -GLAPI void GLAPIENTRY -glProgramLocalParameter4fvARB(GLenum target, GLuint index, - const GLfloat *params) -{ - glProgramLocalParameter4fARB(target, index, params[0], params[1], - params[2], params[3]); -} - - -GLAPI void GLAPIENTRY -glProgramLocalParameter4dARB(GLenum target, GLuint index, - GLdouble x, GLdouble y, GLdouble z, GLdouble w) -{ - glProgramLocalParameter4fARB(target, index, (GLfloat)x, (GLfloat)y, - (GLfloat)z, (GLfloat)w); -} - - -GLAPI void GLAPIENTRY -glProgramLocalParameter4dvARB(GLenum target, GLuint index, - const GLdouble *params) -{ - glProgramLocalParameter4fARB(target, index, (GLfloat)params[0], - (GLfloat)params[1], (GLfloat)params[2], - (GLfloat)params[3]); -} - - -GLAPI void GLAPIENTRY -glGetProgramLocalParameterfvARB(GLenum target, GLuint index, GLfloat *params) -{ - GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END(ctx); - if (target == GL_FRAGMENT_PROGRAM_NV) { - struct fragment_program *fprog = ctx->FragmentProgram.Current; - if (!fprog) { - _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramLocalParameterARB"); - return; - } - if (index >= MAX_NV_FRAGMENT_PROGRAM_PARAMS) { - _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramLocalParameterARB"); - return; - } - params[0] = fprog->LocalParams[index][0]; - params[1] = fprog->LocalParams[index][1]; - params[2] = fprog->LocalParams[index][2]; - params[3] = fprog->LocalParams[index][3]; - } - else { - _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramLocalParameterARB"); - return; - } + _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramNamedParameterNV"); } -GLAPI void GLAPIENTRY -glGetProgramLocalParameterdvARB(GLenum target, GLuint index, GLdouble *params) +void GLAPIENTRY +_mesa_GetProgramNamedParameterdvNV(GLuint id, GLsizei len, const GLubyte *name, + GLdouble *params) { GLfloat floatParams[4]; - glGetProgramLocalParameterfvARB(target, index, floatParams); + _mesa_GetProgramNamedParameterfvNV(id, len, name, floatParams); COPY_4V(params, floatParams); }