Home | History | Annotate | Download | only in main
      1 /*
      2  * Mesa 3-D graphics library
      3  * Version:  6.5.2
      4  *
      5  * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
      6  *
      7  * Permission is hereby granted, free of charge, to any person obtaining a
      8  * copy of this software and associated documentation files (the "Software"),
      9  * to deal in the Software without restriction, including without limitation
     10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     11  * and/or sell copies of the Software, and to permit persons to whom the
     12  * Software is furnished to do so, subject to the following conditions:
     13  *
     14  * The above copyright notice and this permission notice shall be included
     15  * in all copies or substantial portions of the Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     20  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     21  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     23  */
     24 
     25 /**
     26  * \file nvprogram.c
     27  * NVIDIA vertex/fragment program state management functions.
     28  * \author Brian Paul
     29  */
     30 
     31 /*
     32  * Regarding GL_NV_fragment/vertex_program, GL_NV_vertex_program1_1, etc:
     33  *
     34  * Portions of this software may use or implement intellectual
     35  * property owned and licensed by NVIDIA Corporation. NVIDIA disclaims
     36  * any and all warranties with respect to such intellectual property,
     37  * including any use thereof or modifications thereto.
     38  */
     39 
     40 #include "main/glheader.h"
     41 #include "main/context.h"
     42 #include "main/hash.h"
     43 #include "main/imports.h"
     44 #include "main/macros.h"
     45 #include "main/mtypes.h"
     46 #include "main/nvprogram.h"
     47 #include "program/arbprogparse.h"
     48 #include "program/nvfragparse.h"
     49 #include "program/nvvertparse.h"
     50 #include "program/program.h"
     51 #include "program/prog_instruction.h"
     52 #include "program/prog_parameter.h"
     53 
     54 
     55 
     56 /**
     57  * Execute a vertex state program.
     58  * \note Called from the GL API dispatcher.
     59  */
     60 void GLAPIENTRY
     61 _mesa_ExecuteProgramNV(GLenum target, GLuint id, const GLfloat *params)
     62 {
     63    struct gl_vertex_program *vprog;
     64    GET_CURRENT_CONTEXT(ctx);
     65    ASSERT_OUTSIDE_BEGIN_END(ctx);
     66 
     67    if (target != GL_VERTEX_STATE_PROGRAM_NV) {
     68       _mesa_error(ctx, GL_INVALID_ENUM, "glExecuteProgramNV");
     69       return;
     70    }
     71 
     72    FLUSH_VERTICES(ctx, _NEW_PROGRAM);
     73 
     74    vprog = gl_vertex_program(_mesa_lookup_program(ctx, id));
     75 
     76    if (!vprog || vprog->Base.Target != GL_VERTEX_STATE_PROGRAM_NV) {
     77       _mesa_error(ctx, GL_INVALID_OPERATION, "glExecuteProgramNV");
     78       return;
     79    }
     80 
     81    _mesa_problem(ctx, "glExecuteProgramNV() not supported");
     82 }
     83 
     84 
     85 /**
     86  * Determine if a set of programs is resident in hardware.
     87  * \note Not compiled into display lists.
     88  * \note Called from the GL API dispatcher.
     89  */
     90 GLboolean GLAPIENTRY
     91 _mesa_AreProgramsResidentNV(GLsizei n, const GLuint *ids,
     92                             GLboolean *residences)
     93 {
     94    GLint i, j;
     95    GLboolean allResident = GL_TRUE;
     96    GET_CURRENT_CONTEXT(ctx);
     97    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
     98 
     99    if (n < 0) {
    100       _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV(n)");
    101       return GL_FALSE;
    102    }
    103 
    104    for (i = 0; i < n; i++) {
    105       const struct gl_program *prog;
    106       if (ids[i] == 0) {
    107          _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV");
    108          return GL_FALSE;
    109       }
    110       prog = _mesa_lookup_program(ctx, ids[i]);
    111       if (!prog) {
    112          _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV");
    113          return GL_FALSE;
    114       }
    115       if (prog->Resident) {
    116 	 if (!allResident)
    117 	    residences[i] = GL_TRUE;
    118       }
    119       else {
    120          if (allResident) {
    121 	    allResident = GL_FALSE;
    122 	    for (j = 0; j < i; j++)
    123 	       residences[j] = GL_TRUE;
    124 	 }
    125 	 residences[i] = GL_FALSE;
    126       }
    127    }
    128 
    129    return allResident;
    130 }
    131 
    132 
    133 /**
    134  * Request that a set of programs be resident in hardware.
    135  * \note Called from the GL API dispatcher.
    136  */
    137 void GLAPIENTRY
    138 _mesa_RequestResidentProgramsNV(GLsizei n, const GLuint *ids)
    139 {
    140    GLint i;
    141    GET_CURRENT_CONTEXT(ctx);
    142    ASSERT_OUTSIDE_BEGIN_END(ctx);
    143 
    144    if (n < 0) {
    145       _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(n)");
    146       return;
    147    }
    148 
    149    /* just error checking for now */
    150    for (i = 0; i < n; i++) {
    151       struct gl_program *prog;
    152 
    153       if (ids[i] == 0) {
    154          _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(id)");
    155          return;
    156       }
    157 
    158       prog = _mesa_lookup_program(ctx, ids[i]);
    159       if (!prog) {
    160          _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(id)");
    161          return;
    162       }
    163 
    164       /* XXX this is really a hardware thing we should hook out */
    165       prog->Resident = GL_TRUE;
    166    }
    167 }
    168 
    169 
    170 /**
    171  * Get a program parameter register.
    172  * \note Not compiled into display lists.
    173  * \note Called from the GL API dispatcher.
    174  */
    175 void GLAPIENTRY
    176 _mesa_GetProgramParameterfvNV(GLenum target, GLuint index,
    177                               GLenum pname, GLfloat *params)
    178 {
    179    GET_CURRENT_CONTEXT(ctx);
    180    ASSERT_OUTSIDE_BEGIN_END(ctx);
    181 
    182    if (target == GL_VERTEX_PROGRAM_NV) {
    183       if (pname == GL_PROGRAM_PARAMETER_NV) {
    184          if (index < MAX_NV_VERTEX_PROGRAM_PARAMS) {
    185             COPY_4V(params, ctx->VertexProgram.Parameters[index]);
    186          }
    187          else {
    188             _mesa_error(ctx, GL_INVALID_VALUE,
    189                         "glGetProgramParameterfvNV(index)");
    190             return;
    191          }
    192       }
    193       else {
    194          _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterfvNV(pname)");
    195          return;
    196       }
    197    }
    198    else {
    199       _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterfvNV(target)");
    200       return;
    201    }
    202 }
    203 
    204 
    205 /**
    206  * Get a program parameter register.
    207  * \note Not compiled into display lists.
    208  * \note Called from the GL API dispatcher.
    209  */
    210 void GLAPIENTRY
    211 _mesa_GetProgramParameterdvNV(GLenum target, GLuint index,
    212                               GLenum pname, GLdouble *params)
    213 {
    214    GET_CURRENT_CONTEXT(ctx);
    215    ASSERT_OUTSIDE_BEGIN_END(ctx);
    216 
    217    if (target == GL_VERTEX_PROGRAM_NV) {
    218       if (pname == GL_PROGRAM_PARAMETER_NV) {
    219          if (index < MAX_NV_VERTEX_PROGRAM_PARAMS) {
    220             COPY_4V(params, ctx->VertexProgram.Parameters[index]);
    221          }
    222          else {
    223             _mesa_error(ctx, GL_INVALID_VALUE,
    224                         "glGetProgramParameterdvNV(index)");
    225             return;
    226          }
    227       }
    228       else {
    229          _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterdvNV(pname)");
    230          return;
    231       }
    232    }
    233    else {
    234       _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterdvNV(target)");
    235       return;
    236    }
    237 }
    238 
    239 
    240 /**
    241  * Get a program attribute.
    242  * \note Not compiled into display lists.
    243  * \note Called from the GL API dispatcher.
    244  */
    245 void GLAPIENTRY
    246 _mesa_GetProgramivNV(GLuint id, GLenum pname, GLint *params)
    247 {
    248    struct gl_program *prog;
    249    GET_CURRENT_CONTEXT(ctx);
    250 
    251    ASSERT_OUTSIDE_BEGIN_END(ctx);
    252 
    253    prog = _mesa_lookup_program(ctx, id);
    254    if (!prog) {
    255       _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramivNV");
    256       return;
    257    }
    258 
    259    switch (pname) {
    260       case GL_PROGRAM_TARGET_NV:
    261          *params = prog->Target;
    262          return;
    263       case GL_PROGRAM_LENGTH_NV:
    264          *params = prog->String ?(GLint) strlen((char *) prog->String) : 0;
    265          return;
    266       case GL_PROGRAM_RESIDENT_NV:
    267          *params = prog->Resident;
    268          return;
    269       default:
    270          _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivNV(pname)");
    271          return;
    272    }
    273 }
    274 
    275 
    276 /**
    277  * Get the program source code.
    278  * \note Not compiled into display lists.
    279  * \note Called from the GL API dispatcher.
    280  */
    281 void GLAPIENTRY
    282 _mesa_GetProgramStringNV(GLuint id, GLenum pname, GLubyte *program)
    283 {
    284    struct gl_program *prog;
    285    GET_CURRENT_CONTEXT(ctx);
    286 
    287    ASSERT_OUTSIDE_BEGIN_END(ctx);
    288 
    289    if (pname != GL_PROGRAM_STRING_NV) {
    290       _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringNV(pname)");
    291       return;
    292    }
    293 
    294    prog = _mesa_lookup_program(ctx, id);
    295    if (!prog) {
    296       _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramStringNV");
    297       return;
    298    }
    299 
    300    if (prog->String) {
    301       memcpy(program, prog->String, strlen((char *) prog->String));
    302    }
    303    else {
    304       program[0] = 0;
    305    }
    306 }
    307 
    308 
    309 /**
    310  * Get matrix tracking information.
    311  * \note Not compiled into display lists.
    312  * \note Called from the GL API dispatcher.
    313  */
    314 void GLAPIENTRY
    315 _mesa_GetTrackMatrixivNV(GLenum target, GLuint address,
    316                          GLenum pname, GLint *params)
    317 {
    318    GET_CURRENT_CONTEXT(ctx);
    319    ASSERT_OUTSIDE_BEGIN_END(ctx);
    320 
    321    if (target == GL_VERTEX_PROGRAM_NV
    322        && ctx->Extensions.NV_vertex_program) {
    323       GLuint i;
    324 
    325       if ((address & 0x3) || address >= MAX_NV_VERTEX_PROGRAM_PARAMS) {
    326          _mesa_error(ctx, GL_INVALID_VALUE, "glGetTrackMatrixivNV(address)");
    327          return;
    328       }
    329 
    330       i = address / 4;
    331 
    332       switch (pname) {
    333          case GL_TRACK_MATRIX_NV:
    334             params[0] = (GLint) ctx->VertexProgram.TrackMatrix[i];
    335             return;
    336          case GL_TRACK_MATRIX_TRANSFORM_NV:
    337             params[0] = (GLint) ctx->VertexProgram.TrackMatrixTransform[i];
    338             return;
    339          default:
    340             _mesa_error(ctx, GL_INVALID_ENUM, "glGetTrackMatrixivNV");
    341             return;
    342       }
    343    }
    344    else {
    345       _mesa_error(ctx, GL_INVALID_ENUM, "glGetTrackMatrixivNV");
    346       return;
    347    }
    348 }
    349 
    350 
    351 /**
    352  * Get a vertex (or vertex array) attribute.
    353  * \note Not compiled into display lists.
    354  * \note Called from the GL API dispatcher.
    355  */
    356 void GLAPIENTRY
    357 _mesa_GetVertexAttribdvNV(GLuint index, GLenum pname, GLdouble *params)
    358 {
    359    const struct gl_client_array *array;
    360    GET_CURRENT_CONTEXT(ctx);
    361    ASSERT_OUTSIDE_BEGIN_END(ctx);
    362 
    363    if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) {
    364       _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)");
    365       return;
    366    }
    367 
    368    array = &ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)];
    369 
    370    switch (pname) {
    371       case GL_ATTRIB_ARRAY_SIZE_NV:
    372          params[0] = array->Size;
    373          break;
    374       case GL_ATTRIB_ARRAY_STRIDE_NV:
    375          params[0] = array->Stride;
    376          break;
    377       case GL_ATTRIB_ARRAY_TYPE_NV:
    378          params[0] = array->Type;
    379          break;
    380       case GL_CURRENT_ATTRIB_NV:
    381          if (index == 0) {
    382             _mesa_error(ctx, GL_INVALID_OPERATION,
    383                         "glGetVertexAttribdvNV(index == 0)");
    384             return;
    385          }
    386 	 FLUSH_CURRENT(ctx, 0);
    387          COPY_4V(params, ctx->Current.Attrib[index]);
    388          break;
    389       default:
    390          _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV");
    391          return;
    392    }
    393 }
    394 
    395 /**
    396  * Get a vertex (or vertex array) attribute.
    397  * \note Not compiled into display lists.
    398  * \note Called from the GL API dispatcher.
    399  */
    400 void GLAPIENTRY
    401 _mesa_GetVertexAttribfvNV(GLuint index, GLenum pname, GLfloat *params)
    402 {
    403    const struct gl_client_array *array;
    404    GET_CURRENT_CONTEXT(ctx);
    405    ASSERT_OUTSIDE_BEGIN_END(ctx);
    406 
    407    if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) {
    408       _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)");
    409       return;
    410    }
    411 
    412    array = &ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)];
    413 
    414    switch (pname) {
    415       case GL_ATTRIB_ARRAY_SIZE_NV:
    416          params[0] = (GLfloat) array->Size;
    417          break;
    418       case GL_ATTRIB_ARRAY_STRIDE_NV:
    419          params[0] = (GLfloat) array->Stride;
    420          break;
    421       case GL_ATTRIB_ARRAY_TYPE_NV:
    422          params[0] = (GLfloat) array->Type;
    423          break;
    424       case GL_CURRENT_ATTRIB_NV:
    425          if (index == 0) {
    426             _mesa_error(ctx, GL_INVALID_OPERATION,
    427                         "glGetVertexAttribfvNV(index == 0)");
    428             return;
    429          }
    430 	 FLUSH_CURRENT(ctx, 0);
    431          COPY_4V(params, ctx->Current.Attrib[index]);
    432          break;
    433       default:
    434          _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV");
    435          return;
    436    }
    437 }
    438 
    439 /**
    440  * Get a vertex (or vertex array) attribute.
    441  * \note Not compiled into display lists.
    442  * \note Called from the GL API dispatcher.
    443  */
    444 void GLAPIENTRY
    445 _mesa_GetVertexAttribivNV(GLuint index, GLenum pname, GLint *params)
    446 {
    447    const struct gl_client_array *array;
    448    GET_CURRENT_CONTEXT(ctx);
    449    ASSERT_OUTSIDE_BEGIN_END(ctx);
    450 
    451    if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) {
    452       _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)");
    453       return;
    454    }
    455 
    456    array = &ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)];
    457 
    458    switch (pname) {
    459       case GL_ATTRIB_ARRAY_SIZE_NV:
    460          params[0] = array->Size;
    461          break;
    462       case GL_ATTRIB_ARRAY_STRIDE_NV:
    463          params[0] = array->Stride;
    464          break;
    465       case GL_ATTRIB_ARRAY_TYPE_NV:
    466          params[0] = array->Type;
    467          break;
    468       case GL_CURRENT_ATTRIB_NV:
    469          if (index == 0) {
    470             _mesa_error(ctx, GL_INVALID_OPERATION,
    471                         "glGetVertexAttribivNV(index == 0)");
    472             return;
    473          }
    474 	 FLUSH_CURRENT(ctx, 0);
    475          params[0] = (GLint) ctx->Current.Attrib[index][0];
    476          params[1] = (GLint) ctx->Current.Attrib[index][1];
    477          params[2] = (GLint) ctx->Current.Attrib[index][2];
    478          params[3] = (GLint) ctx->Current.Attrib[index][3];
    479          break;
    480       case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB:
    481          params[0] = array->BufferObj->Name;
    482          break;
    483       default:
    484          _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV");
    485          return;
    486    }
    487 }
    488 
    489 
    490 /**
    491  * Get a vertex array attribute pointer.
    492  * \note Not compiled into display lists.
    493  * \note Called from the GL API dispatcher.
    494  */
    495 void GLAPIENTRY
    496 _mesa_GetVertexAttribPointervNV(GLuint index, GLenum pname, GLvoid **pointer)
    497 {
    498    GET_CURRENT_CONTEXT(ctx);
    499    ASSERT_OUTSIDE_BEGIN_END(ctx);
    500 
    501    if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) {
    502       _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribPointerNV(index)");
    503       return;
    504    }
    505 
    506    if (pname != GL_ATTRIB_ARRAY_POINTER_NV) {
    507       _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribPointerNV(pname)");
    508       return;
    509    }
    510 
    511    *pointer = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Ptr;
    512 }
    513 
    514 void
    515 _mesa_emit_nv_temp_initialization(struct gl_context *ctx,
    516 				  struct gl_program *program)
    517 {
    518    struct prog_instruction *inst;
    519    GLuint i;
    520    struct gl_shader_compiler_options* options =
    521          &ctx->ShaderCompilerOptions[_mesa_program_target_to_index(program->Target)];
    522 
    523    if (!options->EmitNVTempInitialization)
    524       return;
    525 
    526    /* We'll swizzle up a zero temporary so we can use it for the
    527     * ARL.
    528     */
    529    if (program->NumTemporaries == 0)
    530       program->NumTemporaries = 1;
    531 
    532    _mesa_insert_instructions(program, 0, program->NumTemporaries + 1);
    533 
    534    for (i = 0; i < program->NumTemporaries; i++) {
    535       struct prog_instruction *inst = &program->Instructions[i];
    536 
    537       inst->Opcode = OPCODE_SWZ;
    538       inst->DstReg.File = PROGRAM_TEMPORARY;
    539       inst->DstReg.Index = i;
    540       inst->DstReg.WriteMask = WRITEMASK_XYZW;
    541       inst->SrcReg[0].File = PROGRAM_TEMPORARY;
    542       inst->SrcReg[0].Index = 0;
    543       inst->SrcReg[0].Swizzle = MAKE_SWIZZLE4(SWIZZLE_ZERO,
    544 					      SWIZZLE_ZERO,
    545 					      SWIZZLE_ZERO,
    546 					      SWIZZLE_ZERO);
    547    }
    548 
    549    inst = &program->Instructions[i];
    550    inst->Opcode = OPCODE_ARL;
    551    inst->DstReg.File = PROGRAM_ADDRESS;
    552    inst->DstReg.Index = 0;
    553    inst->DstReg.WriteMask = WRITEMASK_XYZW;
    554    inst->SrcReg[0].File = PROGRAM_TEMPORARY;
    555    inst->SrcReg[0].Index = 0;
    556    inst->SrcReg[0].Swizzle = SWIZZLE_XXXX;
    557 
    558    if (program->NumAddressRegs == 0)
    559       program->NumAddressRegs = 1;
    560 }
    561 
    562 void
    563 _mesa_setup_nv_temporary_count(struct gl_program *program)
    564 {
    565    GLuint i;
    566 
    567    program->NumTemporaries = 0;
    568    for (i = 0; i < program->NumInstructions; i++) {
    569       struct prog_instruction *inst = &program->Instructions[i];
    570 
    571       if (inst->DstReg.File == PROGRAM_TEMPORARY) {
    572 	 program->NumTemporaries = MAX2(program->NumTemporaries,
    573 					inst->DstReg.Index + 1);
    574       }
    575       if (inst->SrcReg[0].File == PROGRAM_TEMPORARY) {
    576 	 program->NumTemporaries = MAX2((GLint)program->NumTemporaries,
    577 					inst->SrcReg[0].Index + 1);
    578       }
    579       if (inst->SrcReg[1].File == PROGRAM_TEMPORARY) {
    580 	 program->NumTemporaries = MAX2((GLint)program->NumTemporaries,
    581 					inst->SrcReg[1].Index + 1);
    582       }
    583       if (inst->SrcReg[2].File == PROGRAM_TEMPORARY) {
    584 	 program->NumTemporaries = MAX2((GLint)program->NumTemporaries,
    585 					inst->SrcReg[2].Index + 1);
    586       }
    587    }
    588 }
    589 
    590 /**
    591  * Load/parse/compile a program.
    592  * \note Called from the GL API dispatcher.
    593  */
    594 void GLAPIENTRY
    595 _mesa_LoadProgramNV(GLenum target, GLuint id, GLsizei len,
    596                     const GLubyte *program)
    597 {
    598    struct gl_program *prog;
    599    GET_CURRENT_CONTEXT(ctx);
    600    ASSERT_OUTSIDE_BEGIN_END(ctx);
    601 
    602    if (!ctx->Extensions.NV_vertex_program
    603        && !ctx->Extensions.NV_fragment_program) {
    604       _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV()");
    605       return;
    606    }
    607 
    608    if (id == 0) {
    609       _mesa_error(ctx, GL_INVALID_VALUE, "glLoadProgramNV(id)");
    610       return;
    611    }
    612 
    613    if (len < 0) {
    614       _mesa_error(ctx, GL_INVALID_VALUE, "glLoadProgramNV(len)");
    615       return;
    616    }
    617 
    618    FLUSH_VERTICES(ctx, _NEW_PROGRAM);
    619 
    620    prog = _mesa_lookup_program(ctx, id);
    621 
    622    if (prog && prog->Target != 0 && prog->Target != target) {
    623       _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(target)");
    624       return;
    625    }
    626 
    627    if ((target == GL_VERTEX_PROGRAM_NV ||
    628         target == GL_VERTEX_STATE_PROGRAM_NV)
    629        && ctx->Extensions.NV_vertex_program) {
    630       struct gl_vertex_program *vprog = gl_vertex_program(prog);
    631       if (!vprog || prog == &_mesa_DummyProgram) {
    632          vprog = gl_vertex_program(ctx->Driver.NewProgram(ctx, target, id));
    633          if (!vprog) {
    634             _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
    635             return;
    636          }
    637          _mesa_HashInsert(ctx->Shared->Programs, id, vprog);
    638       }
    639 
    640       if (ctx->Extensions.ARB_vertex_program
    641 	  && (strncmp((char *) program, "!!ARB", 5) == 0)) {
    642 	 _mesa_parse_arb_vertex_program(ctx, target, program, len, vprog);
    643       } else {
    644 	 _mesa_parse_nv_vertex_program(ctx, target, program, len, vprog);
    645       }
    646    }
    647    else if (target == GL_FRAGMENT_PROGRAM_NV
    648             && ctx->Extensions.NV_fragment_program) {
    649       struct gl_fragment_program *fprog = gl_fragment_program(prog);
    650       if (!fprog || prog == &_mesa_DummyProgram) {
    651          fprog = gl_fragment_program(ctx->Driver.NewProgram(ctx, target, id));
    652          if (!fprog) {
    653             _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
    654             return;
    655          }
    656          _mesa_HashInsert(ctx->Shared->Programs, id, fprog);
    657       }
    658       _mesa_parse_nv_fragment_program(ctx, target, program, len, fprog);
    659    }
    660    else if (target == GL_FRAGMENT_PROGRAM_ARB
    661             && ctx->Extensions.ARB_fragment_program) {
    662       struct gl_fragment_program *fprog = gl_fragment_program(prog);
    663       if (!fprog || prog == &_mesa_DummyProgram) {
    664          fprog = gl_fragment_program(ctx->Driver.NewProgram(ctx, target, id));
    665          if (!fprog) {
    666             _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
    667             return;
    668          }
    669          _mesa_HashInsert(ctx->Shared->Programs, id, fprog);
    670       }
    671       _mesa_parse_arb_fragment_program(ctx, target, program, len, fprog);
    672    }
    673    else {
    674       _mesa_error(ctx, GL_INVALID_ENUM, "glLoadProgramNV(target)");
    675    }
    676 }
    677 
    678 
    679 
    680 /**
    681  * Set a sequence of program parameter registers.
    682  * \note Called from the GL API dispatcher.
    683  */
    684 void GLAPIENTRY
    685 _mesa_ProgramParameters4dvNV(GLenum target, GLuint index,
    686                              GLsizei num, const GLdouble *params)
    687 {
    688    GET_CURRENT_CONTEXT(ctx);
    689    ASSERT_OUTSIDE_BEGIN_END(ctx);
    690 
    691    if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) {
    692       GLint i;
    693       if (index + num > MAX_NV_VERTEX_PROGRAM_PARAMS) {
    694          _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameters4dvNV");
    695          return;
    696       }
    697       for (i = 0; i < num; i++) {
    698          ctx->VertexProgram.Parameters[index + i][0] = (GLfloat) params[0];
    699          ctx->VertexProgram.Parameters[index + i][1] = (GLfloat) params[1];
    700          ctx->VertexProgram.Parameters[index + i][2] = (GLfloat) params[2];
    701          ctx->VertexProgram.Parameters[index + i][3] = (GLfloat) params[3];
    702          params += 4;
    703       };
    704    }
    705    else {
    706       _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameters4dvNV");
    707       return;
    708    }
    709 }
    710 
    711 
    712 /**
    713  * Set a sequence of program parameter registers.
    714  * \note Called from the GL API dispatcher.
    715  */
    716 void GLAPIENTRY
    717 _mesa_ProgramParameters4fvNV(GLenum target, GLuint index,
    718                              GLsizei num, const GLfloat *params)
    719 {
    720    GET_CURRENT_CONTEXT(ctx);
    721    ASSERT_OUTSIDE_BEGIN_END(ctx);
    722 
    723    if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) {
    724       GLint i;
    725       if (index + num > MAX_NV_VERTEX_PROGRAM_PARAMS) {
    726          _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameters4fvNV");
    727          return;
    728       }
    729       for (i = 0; i < num; i++) {
    730          COPY_4V(ctx->VertexProgram.Parameters[index + i], params);
    731          params += 4;
    732       }
    733    }
    734    else {
    735       _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameters4fvNV");
    736       return;
    737    }
    738 }
    739 
    740 
    741 
    742 /**
    743  * Setup tracking of matrices into program parameter registers.
    744  * \note Called from the GL API dispatcher.
    745  */
    746 void GLAPIENTRY
    747 _mesa_TrackMatrixNV(GLenum target, GLuint address,
    748                     GLenum matrix, GLenum transform)
    749 {
    750    GET_CURRENT_CONTEXT(ctx);
    751    ASSERT_OUTSIDE_BEGIN_END(ctx);
    752 
    753    FLUSH_VERTICES(ctx, _NEW_PROGRAM);
    754 
    755    if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) {
    756       if (address & 0x3) {
    757          /* addr must be multiple of four */
    758          _mesa_error(ctx, GL_INVALID_VALUE, "glTrackMatrixNV(address)");
    759          return;
    760       }
    761 
    762       switch (matrix) {
    763          case GL_NONE:
    764          case GL_MODELVIEW:
    765          case GL_PROJECTION:
    766          case GL_TEXTURE:
    767          case GL_COLOR:
    768          case GL_MODELVIEW_PROJECTION_NV:
    769          case GL_MATRIX0_NV:
    770          case GL_MATRIX1_NV:
    771          case GL_MATRIX2_NV:
    772          case GL_MATRIX3_NV:
    773          case GL_MATRIX4_NV:
    774          case GL_MATRIX5_NV:
    775          case GL_MATRIX6_NV:
    776          case GL_MATRIX7_NV:
    777             /* OK, fallthrough */
    778             break;
    779          default:
    780             _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(matrix)");
    781             return;
    782       }
    783 
    784       switch (transform) {
    785          case GL_IDENTITY_NV:
    786          case GL_INVERSE_NV:
    787          case GL_TRANSPOSE_NV:
    788          case GL_INVERSE_TRANSPOSE_NV:
    789             /* OK, fallthrough */
    790             break;
    791          default:
    792             _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(transform)");
    793             return;
    794       }
    795 
    796       ctx->VertexProgram.TrackMatrix[address / 4] = matrix;
    797       ctx->VertexProgram.TrackMatrixTransform[address / 4] = transform;
    798    }
    799    else {
    800       _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(target)");
    801       return;
    802    }
    803 }
    804 
    805 
    806 void GLAPIENTRY
    807 _mesa_ProgramNamedParameter4fNV(GLuint id, GLsizei len, const GLubyte *name,
    808                                 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
    809 {
    810    struct gl_program *prog;
    811    struct gl_fragment_program *fragProg;
    812    gl_constant_value *v;
    813 
    814    GET_CURRENT_CONTEXT(ctx);
    815    ASSERT_OUTSIDE_BEGIN_END(ctx);
    816 
    817    FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
    818 
    819    prog = _mesa_lookup_program(ctx, id);
    820    if (!prog || prog->Target != GL_FRAGMENT_PROGRAM_NV) {
    821       _mesa_error(ctx, GL_INVALID_OPERATION, "glProgramNamedParameterNV");
    822       return;
    823    }
    824 
    825    if (len <= 0) {
    826       _mesa_error(ctx, GL_INVALID_VALUE, "glProgramNamedParameterNV(len)");
    827       return;
    828    }
    829 
    830    fragProg = gl_fragment_program(prog);
    831    v = _mesa_lookup_parameter_value(fragProg->Base.Parameters, len,
    832                                     (char *) name);
    833    if (v) {
    834       v[0].f = x;
    835       v[1].f = y;
    836       v[2].f = z;
    837       v[3].f = w;
    838       return;
    839    }
    840 
    841    _mesa_error(ctx, GL_INVALID_VALUE, "glProgramNamedParameterNV(name)");
    842 }
    843 
    844 
    845 void GLAPIENTRY
    846 _mesa_ProgramNamedParameter4fvNV(GLuint id, GLsizei len, const GLubyte *name,
    847                                  const float v[])
    848 {
    849    _mesa_ProgramNamedParameter4fNV(id, len, name, v[0], v[1], v[2], v[3]);
    850 }
    851 
    852 
    853 void GLAPIENTRY
    854 _mesa_ProgramNamedParameter4dNV(GLuint id, GLsizei len, const GLubyte *name,
    855                                 GLdouble x, GLdouble y, GLdouble z, GLdouble w)
    856 {
    857    _mesa_ProgramNamedParameter4fNV(id, len, name, (GLfloat)x, (GLfloat)y,
    858                                    (GLfloat)z, (GLfloat)w);
    859 }
    860 
    861 
    862 void GLAPIENTRY
    863 _mesa_ProgramNamedParameter4dvNV(GLuint id, GLsizei len, const GLubyte *name,
    864                                  const double v[])
    865 {
    866    _mesa_ProgramNamedParameter4fNV(id, len, name,
    867                                    (GLfloat)v[0], (GLfloat)v[1],
    868                                    (GLfloat)v[2], (GLfloat)v[3]);
    869 }
    870 
    871 
    872 void GLAPIENTRY
    873 _mesa_GetProgramNamedParameterfvNV(GLuint id, GLsizei len, const GLubyte *name,
    874                                    GLfloat *params)
    875 {
    876    struct gl_program *prog;
    877    struct gl_fragment_program *fragProg;
    878    const gl_constant_value *v;
    879 
    880    GET_CURRENT_CONTEXT(ctx);
    881 
    882    ASSERT_OUTSIDE_BEGIN_END(ctx);
    883 
    884    prog = _mesa_lookup_program(ctx, id);
    885    if (!prog || prog->Target != GL_FRAGMENT_PROGRAM_NV) {
    886       _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramNamedParameterNV");
    887       return;
    888    }
    889 
    890    if (len <= 0) {
    891       _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramNamedParameterNV");
    892       return;
    893    }
    894 
    895    fragProg = gl_fragment_program(prog);
    896    v = _mesa_lookup_parameter_value(fragProg->Base.Parameters,
    897                                     len, (char *) name);
    898    if (v) {
    899       params[0] = v[0].f;
    900       params[1] = v[1].f;
    901       params[2] = v[2].f;
    902       params[3] = v[3].f;
    903       return;
    904    }
    905 
    906    _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramNamedParameterNV");
    907 }
    908 
    909 
    910 void GLAPIENTRY
    911 _mesa_GetProgramNamedParameterdvNV(GLuint id, GLsizei len, const GLubyte *name,
    912                                    GLdouble *params)
    913 {
    914    GLfloat floatParams[4];
    915    _mesa_GetProgramNamedParameterfvNV(id, len, name, floatParams);
    916    COPY_4V(params, floatParams);
    917 }
    918