Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

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