home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mesa5.zip / mesa5src.zip / MesaDLL / vpstate.cpp < prev    next >
C/C++ Source or Header  |  2002-12-10  |  27KB  |  952 lines

  1. /* $Id: vpstate.c,v 1.13 2002/11/27 03:40:13 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  5.1
  6.  *
  7.  * Copyright (C) 1999-2002  Brian Paul   All Rights Reserved.
  8.  *
  9.  * Permission is hereby granted, free of charge, to any person obtaining a
  10.  * copy of this software and associated documentation files (the "Software"),
  11.  * to deal in the Software without restriction, including without limitation
  12.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  13.  * and/or sell copies of the Software, and to permit persons to whom the
  14.  * Software is furnished to do so, subject to the following conditions:
  15.  *
  16.  * The above copyright notice and this permission notice shall be included
  17.  * in all copies or substantial portions of the Software.
  18.  *
  19.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  20.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  22.  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  23.  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  24.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  */
  26.  
  27. /*
  28.  * -------- Regarding NV_vertex_program --------
  29.  * Redistribution and use in source and binary forms, with or without
  30.  * modification, are permitted provided that the following conditions are met:
  31.  * 
  32.  * o Redistribution of the source code must contain a copyright notice
  33.  *   and this list of conditions;
  34.  * 
  35.  * o Redistribution in binary and source code form must contain the
  36.  *   following Notice in the software and any documentation and/or other
  37.  *   materials provided with the distribution; and
  38.  * 
  39.  * o The name of Nvidia may not be used to promote or endorse software
  40.  *   derived from the software.
  41.  * 
  42.  * NOTICE: Nvidia hereby grants to each recipient a non-exclusive worldwide
  43.  * royalty free patent license under patent claims that are licensable by
  44.  * Nvidia and which are necessarily required and for which no commercially
  45.  * viable non infringing alternative exists to make, use, sell, offer to sell,
  46.  * import and otherwise transfer the vertex extension for the Mesa 3D Graphics
  47.  * Library as distributed in source code and object code form.  No hardware or
  48.  * hardware implementation (including a semiconductor implementation and chips)
  49.  * are licensed hereunder. If a recipient makes a patent claim or institutes
  50.  * patent litigation against Nvidia or Nvidia's customers for use or sale of
  51.  * Nvidia products, then this license grant as to such recipient shall
  52.  * immediately terminate and recipient immediately agrees to cease use and
  53.  * distribution of the Mesa Program and derivatives thereof. 
  54.  * 
  55.  * THE MESA 3D GRAPHICS LIBRARY IS PROVIDED ON AN "AS IS BASIS, WITHOUT
  56.  * WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING,
  57.  * WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-NFRINGEMENT
  58.  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
  59.  * 
  60.  * NVIDIA SHALL NOT HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  61.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION
  62.  * LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  63.  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  64.  * ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE MESA 3D GRAPHICS
  65.  * LIBRARY OR EVIDENCE OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDR, EVEN
  66.  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  67.  * 
  68.  * If you do not comply with this agreement, then Nvidia may cancel the license
  69.  * and rights granted herein.
  70.  * ---------------------------------------------
  71.  */
  72.  
  73. /**
  74.  * \file vpstate.c
  75.  * \brief Vertex program state management functions (most map to API functions)
  76.  * \author Brian Paul
  77.  */
  78.  
  79.  
  80. #include "glheader.h"
  81. #include "context.h"
  82. #include "hash.h"
  83. #include "imports.h"
  84. #include "macros.h"
  85. #include "mtypes.h"
  86. #include "vpexec.h"
  87. #include "vpparse.h"
  88. #include "vpstate.h"
  89.  
  90.  
  91. /**
  92.  * Delete a program and remove it from the hash table, ignoring the
  93.  * reference count.
  94.  * \note Called from the GL API dispatcher.
  95.  */
  96. void _mesa_delete_program(GLcontext *ctx, GLuint id)
  97. {
  98.    struct vp_program *vprog = (struct vp_program *)
  99.       _mesa_HashLookup(ctx->Shared->VertexPrograms, id);
  100.  
  101.    if (vprog) {
  102.       if (vprog->String)
  103.          FREE(vprog->String);
  104.       if (vprog->Instructions)
  105.          FREE(vprog->Instructions);
  106.       _mesa_HashRemove(ctx->Shared->VertexPrograms, id);
  107.       FREE(vprog);
  108.    }
  109. }
  110.  
  111.  
  112. /**
  113.  * Bind a program (make it current)
  114.  * \note Called from the GL API dispatcher.
  115.  */
  116. void _mesa_BindProgramNV(GLenum target, GLuint id)
  117. {
  118.    struct vp_program *vprog;
  119.    GET_CURRENT_CONTEXT(ctx);
  120.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  121.  
  122.    if (target != GL_VERTEX_PROGRAM_NV) {
  123.       _mesa_error(ctx, GL_INVALID_ENUM, "glBindProgramNV");
  124.       return;
  125.    }
  126.  
  127.    if (id == ctx->VertexProgram.CurrentID)
  128.       return;
  129.  
  130.    /* decrement refcount on previously bound vertex program */
  131.    if (ctx->VertexProgram.Current) {
  132.       ctx->VertexProgram.Current->RefCount--;
  133.       /* and delete if refcount goes below one */
  134.       if (ctx->VertexProgram.Current->RefCount <= 0)
  135.          _mesa_delete_program(ctx, ctx->VertexProgram.CurrentID);
  136.    }
  137.  
  138.    /* NOTE: binding to a non-existant program is not an error.
  139.     * That's supposed to be caught in glBegin.
  140.     */
  141.    vprog = (struct vp_program *)
  142.       _mesa_HashLookup(ctx->Shared->VertexPrograms, id);
  143.  
  144.    if (!vprog && id > 0){
  145.       /* new program ID */
  146.       vprog = CALLOC_STRUCT(vp_program);
  147.       if (!vprog) {
  148.          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindProgramNV");
  149.          return;
  150.       }
  151.       vprog->Target = target;
  152.       vprog->Resident = GL_TRUE;
  153.       vprog->RefCount = 1;
  154.       _mesa_HashInsert(ctx->Shared->VertexPrograms, id, vprog);
  155.    }
  156.  
  157.    ctx->VertexProgram.CurrentID = id;
  158.    ctx->VertexProgram.Current = vprog;
  159.    if (vprog)
  160.       vprog->RefCount++;
  161. }
  162.  
  163.  
  164. /**
  165.  * Delete a list of programs.
  166.  * \note Not compiled into display lists.
  167.  * \note Called from the GL API dispatcher.
  168.  */
  169. void _mesa_DeleteProgramsNV(GLsizei n, const GLuint *ids)
  170. {
  171.    GLint i;
  172.    GET_CURRENT_CONTEXT(ctx);
  173.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  174.  
  175.    if (n < 0) {
  176.       _mesa_error( ctx, GL_INVALID_VALUE, "glDeleteProgramsNV" );
  177.       return;
  178.    }
  179.  
  180.    for (i = 0; i < n; i++) {
  181.       if (ids[i] != 0) {
  182.          struct vp_program *vprog = (struct vp_program *)
  183.             _mesa_HashLookup(ctx->Shared->VertexPrograms, ids[i]);
  184.          if (ctx->VertexProgram.CurrentID == ids[i]) {
  185.             /* unbind this currently bound program */
  186.             _mesa_BindProgramNV(vprog->Target, 0);
  187.          }
  188.          if (vprog) {
  189.             vprog->RefCount--;
  190.             if (vprog->RefCount <= 0) {
  191.                _mesa_delete_program(ctx, ids[i]);
  192.             }
  193.          }
  194.       }
  195.    }
  196. }
  197.  
  198.  
  199. /**
  200.  * Execute a vertex state program.
  201.  * \note Called from the GL API dispatcher.
  202.  */
  203. void _mesa_ExecuteProgramNV(GLenum target, GLuint id, const GLfloat *params)
  204. {
  205.    struct vp_program *vprog;
  206.    GET_CURRENT_CONTEXT(ctx);
  207.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  208.  
  209.    if (target != GL_VERTEX_STATE_PROGRAM_NV) {
  210.       _mesa_error(ctx, GL_INVALID_ENUM, "glExecuteProgramNV");
  211.       return;
  212.    }
  213.  
  214.    vprog = (struct vp_program *)
  215.       _mesa_HashLookup(ctx->Shared->VertexPrograms, id);
  216.  
  217.    if (!vprog || vprog->Target != GL_VERTEX_STATE_PROGRAM_NV) {
  218.       _mesa_error(ctx, GL_INVALID_OPERATION, "glExecuteProgramNV");
  219.       return;
  220.    }
  221.    
  222.    _mesa_init_vp_registers(ctx);
  223.    _mesa_init_tracked_matrices(ctx);
  224.    COPY_4V(ctx->VertexProgram.Machine.Registers[VP_INPUT_REG_START], params);
  225.    _mesa_exec_program(ctx, vprog);
  226. }
  227.  
  228.  
  229. /**
  230.  * Generate a list of new program identifiers.
  231.  * \note Not compiled into display lists.
  232.  * \note Called from the GL API dispatcher.
  233.  */
  234. void _mesa_GenProgramsNV(GLsizei n, GLuint *ids)
  235. {
  236.    GLuint first;
  237.    GLuint i;
  238.    GET_CURRENT_CONTEXT(ctx);
  239.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  240.  
  241.    if (n < 0) {
  242.       _mesa_error(ctx, GL_INVALID_VALUE, "glGenProgramsNV");
  243.       return;
  244.    }
  245.  
  246.    if (!ids)
  247.       return;
  248.  
  249.    first = _mesa_HashFindFreeKeyBlock(ctx->Shared->VertexPrograms, n);
  250.  
  251.    for (i = 0; i < (GLuint) n; i++) {
  252.       struct vp_program *vprog = CALLOC_STRUCT(vp_program);
  253.       if (!vprog) {
  254.          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenProgramsNV");
  255.          return;
  256.       }
  257.       vprog->RefCount = 1;
  258.       _mesa_HashInsert(ctx->Shared->VertexPrograms, first + i, vprog);
  259.    }
  260.  
  261.    /* Return the program names */
  262.    for (i = 0; i < (GLuint) n; i++) {
  263.       ids[i] = first + i;
  264.    }
  265. }
  266.  
  267.  
  268. /**
  269.  * Determine if a set of programs is resident in hardware.
  270.  * \note Not compiled into display lists.
  271.  * \note Called from the GL API dispatcher.
  272.  */
  273. GLboolean _mesa_AreProgramsResidentNV(GLsizei n, const GLuint *ids,
  274.                                       GLboolean *residences)
  275. {
  276.    GLint i;
  277.    GLboolean retVal;
  278.    GET_CURRENT_CONTEXT(ctx);
  279.    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
  280.  
  281.    if (n < 0) {
  282.       _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV(n)");
  283.       return GL_FALSE;
  284.    }
  285.  
  286.    retVal = GL_TRUE;
  287.  
  288.    for (i = 0; i < n; i++) {
  289.       struct vp_program *vprog;
  290.  
  291.       if (ids[i] == 0) {
  292.          _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV(id)");
  293.          return GL_FALSE;
  294.       }
  295.  
  296.       vprog = (struct vp_program *)
  297.          _mesa_HashLookup(ctx->Shared->VertexPrograms, ids[i]);
  298.  
  299.       if (!vprog) {
  300.          _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV(id)");
  301.          return GL_FALSE;
  302.       }
  303.  
  304.       *residences = vprog->Resident;
  305.       if (!vprog->Resident)
  306.          retVal = GL_FALSE;
  307.    }
  308.  
  309.    return retVal;
  310. }
  311.  
  312.  
  313. /**
  314.  * Request that a set of programs be resident in hardware.
  315.  * \note Called from the GL API dispatcher.
  316.  */
  317. void _mesa_RequestResidentProgramsNV(GLsizei n, const GLuint *ids)
  318. {
  319.    GLint i;
  320.    GET_CURRENT_CONTEXT(ctx);
  321.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  322.  
  323.    if (n < 0) {
  324.       _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(n)");
  325.       return;
  326.    }
  327.  
  328.    /* just error checking for now */
  329.    for (i = 0; i < n; i++) {
  330.       struct vp_program *vprog;
  331.  
  332.       if (ids[i] == 0) {
  333.          _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(id)");
  334.          return;
  335.       }
  336.  
  337.       vprog = (struct vp_program *)
  338.          _mesa_HashLookup(ctx->Shared->VertexPrograms, ids[i]);
  339.  
  340.       if (!vprog) {
  341.          _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(id)");
  342.          return;
  343.       }
  344.  
  345.       vprog->Resident = GL_TRUE;
  346.    }
  347. }
  348.  
  349.  
  350. /**
  351.  * Get a program parameter register.
  352.  * \note Not compiled into display lists.
  353.  * \note Called from the GL API dispatcher.
  354.  */
  355. void _mesa_GetProgramParameterfvNV(GLenum target, GLuint index,
  356.                                    GLenum pname, GLfloat *params)
  357. {
  358.    GET_CURRENT_CONTEXT(ctx);
  359.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  360.  
  361.    if (target != GL_VERTEX_PROGRAM_NV) {
  362.       _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterfvNV");
  363.       return;
  364.    }
  365.  
  366.    if (index >= VP_NUM_PROG_REGS) {
  367.       _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramParameterfvNV");
  368.       return;
  369.    }
  370.  
  371.    if (pname != GL_PROGRAM_PARAMETER_NV) {
  372.       _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterfvNV");
  373.       return;
  374.    }
  375.  
  376.    index += VP_PROG_REG_START;
  377.    COPY_4V(params, ctx->VertexProgram.Machine.Registers[index]);
  378. }
  379.  
  380.  
  381. /**
  382.  * Get a program parameter register.
  383.  * \note Not compiled into display lists.
  384.  * \note Called from the GL API dispatcher.
  385.  */
  386. void _mesa_GetProgramParameterdvNV(GLenum target, GLuint index,
  387.                                    GLenum pname, GLdouble *params)
  388. {
  389.    GET_CURRENT_CONTEXT(ctx);
  390.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  391.  
  392.    if (target != GL_VERTEX_PROGRAM_NV) {
  393.       _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterfvNV");
  394.       return;
  395.    }
  396.  
  397.    if (index >= VP_NUM_PROG_REGS) {
  398.       _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramParameterfvNV");
  399.       return;
  400.    }
  401.  
  402.    if (pname != GL_PROGRAM_PARAMETER_NV) {
  403.       _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterfvNV");
  404.       return;
  405.    }
  406.  
  407.    index += VP_PROG_REG_START;
  408.    COPY_4V(params, ctx->VertexProgram.Machine.Registers[index]);
  409. }
  410.  
  411.  
  412. /**
  413.  * Get a program attribute.
  414.  * \note Not compiled into display lists.
  415.  * \note Called from the GL API dispatcher.
  416.  */
  417. void _mesa_GetProgramivNV(GLuint id, GLenum pname, GLint *params)
  418. {
  419.    struct vp_program *vprog;
  420.    GET_CURRENT_CONTEXT(ctx);
  421.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  422.  
  423.    vprog = (struct vp_program *)
  424.       _mesa_HashLookup(ctx->Shared->VertexPrograms, id);
  425.  
  426.    if (!vprog) {
  427.       _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramivNV");
  428.       return;
  429.    }
  430.  
  431.    switch (pname) {
  432.       case GL_PROGRAM_TARGET_NV:
  433.          *params = vprog->Target;
  434.          return;
  435.       case GL_PROGRAM_LENGTH_NV:
  436.          *params = vprog->String ? _mesa_strlen((char *) vprog->String) : 0;
  437.          return;
  438.       case GL_PROGRAM_RESIDENT_NV:
  439.          *params = vprog->Resident;
  440.          return;
  441.       default:
  442.          _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivNV(pname)");
  443.          return;
  444.    }
  445. }
  446.  
  447.  
  448. /**
  449.  * Get the program source code.
  450.  * \note Not compiled into display lists.
  451.  * \note Called from the GL API dispatcher.
  452.  */
  453. void _mesa_GetProgramStringNV(GLuint id, GLenum pname, GLubyte *program)
  454. {
  455.    struct vp_program *vprog;
  456.    GET_CURRENT_CONTEXT(ctx);
  457.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  458.  
  459.    if (pname != GL_PROGRAM_STRING_NV) {
  460.       _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivNV(pname)");
  461.       return;
  462.    }
  463.  
  464.    vprog = (struct vp_program *)
  465.       _mesa_HashLookup(ctx->Shared->VertexPrograms, id);
  466.  
  467.    if (!vprog) {
  468.       _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramivNV");
  469.       return;
  470.    }
  471.  
  472.    if (vprog->String) {
  473.       MEMCPY(program, vprog->String, _mesa_strlen((char *) vprog->String));
  474.    }
  475.    else {
  476.       program[0] = 0;
  477.    }
  478. }
  479.  
  480.  
  481. /**
  482.  * Get matrix tracking information.
  483.  * \note Not compiled into display lists.
  484.  * \note Called from the GL API dispatcher.
  485.  */
  486. void _mesa_GetTrackMatrixivNV(GLenum target, GLuint address,
  487.                               GLenum pname, GLint *params)
  488. {
  489.    GLuint i;
  490.    GET_CURRENT_CONTEXT(ctx);
  491.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  492.  
  493.    if (target != GL_VERTEX_PROGRAM_NV) {
  494.       _mesa_error(ctx, GL_INVALID_ENUM, "glGetTrackMatrixivNV");
  495.       return;
  496.    }
  497.  
  498.    if ((address & 0x3) || address > VP_NUM_PROG_REGS) {
  499.       _mesa_error(ctx, GL_INVALID_VALUE, "glGetTrackMatrixivNV(address)");
  500.       return;
  501.    }
  502.  
  503.    i = address / 4;
  504.  
  505.    switch (pname) {
  506.       case GL_TRACK_MATRIX_NV:
  507.          params[0] = (GLint) ctx->VertexProgram.TrackMatrix[i];
  508.          return;
  509.       case GL_TRACK_MATRIX_TRANSFORM_NV:
  510.          params[0] = (GLint) ctx->VertexProgram.TrackMatrixTransform[i];
  511.          return;
  512.       default:
  513.          _mesa_error(ctx, GL_INVALID_ENUM, "glGetTrackMatrixivNV");
  514.          return;
  515.    }
  516. }
  517.  
  518.  
  519. /**
  520.  * Get a vertex (or vertex array) attribute.
  521.  * \note Not compiled into display lists.
  522.  * \note Called from the GL API dispatcher.
  523.  */
  524. void _mesa_GetVertexAttribdvNV(GLuint index, GLenum pname, GLdouble *params)
  525. {
  526.    GET_CURRENT_CONTEXT(ctx);
  527.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  528.  
  529.    if (index == 0 || index >= VP_NUM_INPUT_REGS) {
  530.       _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)");
  531.       return;
  532.    }
  533.  
  534.    switch (pname) {
  535.       case GL_ATTRIB_ARRAY_SIZE_NV:
  536.          params[0] = ctx->Array.VertexAttrib[index].Size;
  537.          break;
  538.       case GL_ATTRIB_ARRAY_STRIDE_NV:
  539.          params[0] = ctx->Array.VertexAttrib[index].Stride;
  540.          break;
  541.       case GL_ATTRIB_ARRAY_TYPE_NV:
  542.          params[0] = ctx->Array.VertexAttrib[index].Type;
  543.          break;
  544.       case GL_CURRENT_ATTRIB_NV:
  545.          COPY_4V(params, ctx->Current.Attrib[index]);
  546.          break;
  547.       default:
  548.          _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV");
  549.          return;
  550.    }
  551. }
  552.  
  553. /**
  554.  * Get a vertex (or vertex array) attribute.
  555.  * \note Not compiled into display lists.
  556.  * \note Called from the GL API dispatcher.
  557.  */
  558. void _mesa_GetVertexAttribfvNV(GLuint index, GLenum pname, GLfloat *params)
  559. {
  560.    GET_CURRENT_CONTEXT(ctx);
  561.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  562.  
  563.    if (index == 0 || index >= VP_NUM_INPUT_REGS) {
  564.       _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)");
  565.       return;
  566.    }
  567.  
  568.    switch (pname) {
  569.       case GL_ATTRIB_ARRAY_SIZE_NV:
  570.          params[0] = (GLfloat) ctx->Array.VertexAttrib[index].Size;
  571.          break;
  572.       case GL_ATTRIB_ARRAY_STRIDE_NV:
  573.          params[0] = (GLfloat) ctx->Array.VertexAttrib[index].Stride;
  574.          break;
  575.       case GL_ATTRIB_ARRAY_TYPE_NV:
  576.          params[0] = (GLfloat) ctx->Array.VertexAttrib[index].Type;
  577.          break;
  578.       case GL_CURRENT_ATTRIB_NV:
  579.          COPY_4V(params, ctx->Current.Attrib[index]);
  580.          break;
  581.       default:
  582.          _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV");
  583.          return;
  584.    }
  585. }
  586.  
  587. /**
  588.  * Get a vertex (or vertex array) attribute.
  589.  * \note Not compiled into display lists.
  590.  * \note Called from the GL API dispatcher.
  591.  */
  592. void _mesa_GetVertexAttribivNV(GLuint index, GLenum pname, GLint *params)
  593. {
  594.    GET_CURRENT_CONTEXT(ctx);
  595.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  596.  
  597.    if (index == 0 || index >= VP_NUM_INPUT_REGS) {
  598.       _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)");
  599.       return;
  600.    }
  601.  
  602.    switch (pname) {
  603.       case GL_ATTRIB_ARRAY_SIZE_NV:
  604.          params[0] = ctx->Array.VertexAttrib[index].Size;
  605.          break;
  606.       case GL_ATTRIB_ARRAY_STRIDE_NV:
  607.          params[0] = ctx->Array.VertexAttrib[index].Stride;
  608.          break;
  609.       case GL_ATTRIB_ARRAY_TYPE_NV:
  610.          params[0] = ctx->Array.VertexAttrib[index].Type;
  611.          break;
  612.       case GL_CURRENT_ATTRIB_NV:
  613.          COPY_4V_CAST(params, ctx->Current.Attrib[index], GLint);
  614.          break;
  615.       default:
  616.          _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV");
  617.          return;
  618.    }
  619. }
  620.  
  621.  
  622. /**
  623.  * Get a vertex array attribute pointer.
  624.  * \note Not compiled into display lists.
  625.  * \note Called from the GL API dispatcher.
  626.  */
  627. void _mesa_GetVertexAttribPointervNV(GLuint index, GLenum pname, GLvoid **pointer)
  628. {
  629.    GET_CURRENT_CONTEXT(ctx);
  630.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  631.  
  632.    if (index >= VP_NUM_PROG_REGS) {
  633.       _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribPointerNV(index)");
  634.       return;
  635.    }
  636.  
  637.    if (pname != GL_ATTRIB_ARRAY_POINTER_NV) {
  638.       _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribPointerNV(pname)");
  639.       return;
  640.    }
  641.  
  642.    *pointer = ctx->Array.VertexAttrib[index].Ptr;
  643. }
  644.  
  645.  
  646. /**
  647.  * Determine if id names a program.
  648.  * \note Not compiled into display lists.
  649.  * \note Called from the GL API dispatcher.
  650.  * \param id is the program identifier
  651.  * \return GL_TRUE if id is a program, else GL_FALSE.
  652.  */
  653. GLboolean _mesa_IsProgramNV(GLuint id)
  654. {
  655.    struct vp_program *vprog;
  656.    GET_CURRENT_CONTEXT(ctx);
  657.    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
  658.  
  659.    if (id == 0)
  660.       return GL_FALSE;
  661.  
  662.    vprog = (struct vp_program *)
  663.       _mesa_HashLookup(ctx->Shared->VertexPrograms, id);
  664.  
  665.    if (vprog && vprog->Target)
  666.       return GL_TRUE;
  667.    else
  668.       return GL_FALSE;
  669. }
  670.  
  671.  
  672. /**
  673.  * Load a vertex program.
  674.  * \note Called from the GL API dispatcher.
  675.  */
  676. void _mesa_LoadProgramNV(GLenum target, GLuint id, GLsizei len,
  677.                          const GLubyte *program)
  678. {
  679.    struct vp_program *vprog;
  680.    GLboolean newProgram = GL_FALSE;
  681.    GLubyte *programCopy;
  682.    GET_CURRENT_CONTEXT(ctx);
  683.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  684.  
  685.    if (id == 0) {
  686.       _mesa_error(ctx, GL_INVALID_VALUE, "glLoadProgramNV(id)");
  687.       return;
  688.    }
  689.  
  690.    vprog = (struct vp_program *)
  691.       _mesa_HashLookup(ctx->Shared->VertexPrograms, id);
  692.  
  693.    if (vprog && vprog->Target != 0 && vprog->Target != target) {
  694.       _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(target)");
  695.       return;
  696.    }
  697.  
  698.    /* make a copy of the program string so that we can null-terminate it */
  699.    /* if we change the parser to stop after <len> characters, instead of */
  700.    /* looking for '\0' we can eliminate this. */
  701.    programCopy = (GLubyte *) MALLOC(len + 1);
  702.    if (!programCopy) {
  703.       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
  704.       return;
  705.    }
  706.    MEMCPY(programCopy, program, len);
  707.    programCopy[len] = 0;
  708.  
  709.    if (!vprog) {
  710.       newProgram = GL_TRUE;
  711.       vprog = CALLOC_STRUCT(vp_program);
  712.       if (!vprog) {
  713.          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
  714.          return;
  715.       }
  716.    }
  717.  
  718.    _mesa_parse_vertex_program(ctx, target, programCopy, len, vprog);
  719.    if (ctx->VertexProgram.ErrorPos == -1) {
  720.       /* loaded and parsed w/out errors */
  721.       if (newProgram) {
  722.          _mesa_HashInsert(ctx->Shared->VertexPrograms, id, vprog);
  723.       }
  724.       vprog->RefCount = 1;
  725.       vprog->Resident = GL_TRUE;
  726.    }
  727.  
  728.    FREE(programCopy);
  729. }
  730.  
  731.  
  732.  
  733. /**
  734.  * Set a program parameter register.
  735.  * \note Called from the GL API dispatcher.
  736.  */
  737. void _mesa_ProgramParameter4dNV(GLenum target, GLuint index,
  738.                                 GLdouble x, GLdouble y, GLdouble z, GLdouble w)
  739. {
  740.    GET_CURRENT_CONTEXT(ctx);
  741.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  742.  
  743.    if (target != GL_VERTEX_PROGRAM_NV) {
  744.       _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameter4dNV");
  745.       return;
  746.    }
  747.  
  748.    if (index >= VP_NUM_PROG_REGS) {
  749.       _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameter4dNV");
  750.       return;
  751.    }
  752.  
  753.    index += VP_PROG_REG_START;
  754.    ASSIGN_4V(ctx->VertexProgram.Machine.Registers[index], 
  755.          (GLfloat)x, (GLfloat)y, (GLfloat)z, (GLfloat)w);
  756. }
  757.  
  758.  
  759. /**
  760.  * Set a program parameter register.
  761.  * \note Called from the GL API dispatcher.
  762.  */
  763. void _mesa_ProgramParameter4dvNV(GLenum target, GLuint index,
  764.                                  const GLdouble *params)
  765. {
  766.    GET_CURRENT_CONTEXT(ctx);
  767.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  768.  
  769.    if (target != GL_VERTEX_PROGRAM_NV) {
  770.       _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameter4dvNV");
  771.       return;
  772.    }
  773.  
  774.    if (index >= VP_NUM_PROG_REGS) {
  775.       _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameter4dvNV");
  776.       return;
  777.    }
  778.  
  779.    index += VP_PROG_REG_START;
  780.    COPY_4V_CAST(ctx->VertexProgram.Machine.Registers[index], params, GLfloat);
  781. }
  782.  
  783.  
  784. /**
  785.  * Set a program parameter register.
  786.  * \note Called from the GL API dispatcher.
  787.  */
  788. void _mesa_ProgramParameter4fNV(GLenum target, GLuint index,
  789.                                 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
  790. {
  791.    GET_CURRENT_CONTEXT(ctx);
  792.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  793.  
  794.    if (target != GL_VERTEX_PROGRAM_NV) {
  795.       _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameter4fNV");
  796.       return;
  797.    }
  798.  
  799.    if (index >= VP_NUM_PROG_REGS) {
  800.       _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameter4fNV");
  801.       return;
  802.    }
  803.  
  804.    index += VP_PROG_REG_START;
  805.    ASSIGN_4V(ctx->VertexProgram.Machine.Registers[index], x, y, z, w);
  806. }
  807.  
  808.  
  809. /**
  810.  * Set a program parameter register.
  811.  * \note Called from the GL API dispatcher.
  812.  */
  813. void _mesa_ProgramParameter4fvNV(GLenum target, GLuint index,
  814.                                  const GLfloat *params)
  815. {
  816.    GET_CURRENT_CONTEXT(ctx);
  817.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  818.  
  819.    if (target != GL_VERTEX_PROGRAM_NV) {
  820.       _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameter4fNV");
  821.       return;
  822.    }
  823.  
  824.    if (index >= VP_NUM_PROG_REGS) {
  825.       _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameter4fNV");
  826.       return;
  827.    }
  828.  
  829.    index += VP_PROG_REG_START;
  830.    COPY_4V(ctx->VertexProgram.Machine.Registers[index], params);
  831. }
  832.  
  833.  
  834. /**
  835.  * Set a sequence of program parameter registers.
  836.  * \note Called from the GL API dispatcher.
  837.  */
  838. void _mesa_ProgramParameters4dvNV(GLenum target, GLuint index,
  839.                                   GLuint num, const GLdouble *params)
  840. {
  841.    GLuint i;
  842.    GET_CURRENT_CONTEXT(ctx);
  843.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  844.  
  845.    if (target != GL_VERTEX_PROGRAM_NV) {
  846.       _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameters4dvNV");
  847.       return;
  848.    }
  849.  
  850.    if (index + num > VP_NUM_PROG_REGS) {
  851.       _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameters4dvNV");
  852.       return;
  853.    }
  854.  
  855.    index += VP_PROG_REG_START;
  856.    for (i = 0; i < num; i++) {
  857.       COPY_4V_CAST(ctx->VertexProgram.Machine.Registers[index + i], 
  858.            params, GLfloat);
  859.       params += 4;
  860.    };
  861. }
  862.  
  863.  
  864. /**
  865.  * Set a sequence of program parameter registers.
  866.  * \note Called from the GL API dispatcher.
  867.  */
  868. void _mesa_ProgramParameters4fvNV(GLenum target, GLuint index,
  869.                                   GLuint num, const GLfloat *params)
  870. {
  871.    GLuint i;
  872.    GET_CURRENT_CONTEXT(ctx);
  873.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  874.  
  875.    if (target != GL_VERTEX_PROGRAM_NV) {
  876.       _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameters4fvNV");
  877.       return;
  878.    }
  879.  
  880.    if (index + num > VP_NUM_PROG_REGS) {
  881.       _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameters4fvNV");
  882.       return;
  883.    }
  884.  
  885.    index += VP_PROG_REG_START;
  886.    for (i = 0; i < num; i++) {
  887.       COPY_4V(ctx->VertexProgram.Machine.Registers[index + i], params);
  888.       params += 4;
  889.    };
  890. }
  891.  
  892.  
  893.  
  894. /**
  895.  * Setup tracking of matrices into program parameter registers.
  896.  * \note Called from the GL API dispatcher.
  897.  */
  898. void _mesa_TrackMatrixNV(GLenum target, GLuint address,
  899.                          GLenum matrix, GLenum transform)
  900. {
  901.    GET_CURRENT_CONTEXT(ctx);
  902.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  903.  
  904.    if (target != GL_VERTEX_PROGRAM_NV) {
  905.       _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(target)");
  906.       return;
  907.    }
  908.  
  909.    if (address & 0x3) {
  910.       /* addr must be multiple of four */
  911.       _mesa_error(ctx, GL_INVALID_VALUE, "glTrackMatrixNV(address)");
  912.       return;
  913.    }
  914.  
  915.    switch (matrix) {
  916.       case GL_NONE:
  917.       case GL_MODELVIEW:
  918.       case GL_PROJECTION:
  919.       case GL_TEXTURE:
  920.       case GL_COLOR:
  921.       case GL_MODELVIEW_PROJECTION_NV:
  922.       case GL_MATRIX0_NV:
  923.       case GL_MATRIX1_NV:
  924.       case GL_MATRIX2_NV:
  925.       case GL_MATRIX3_NV:
  926.       case GL_MATRIX4_NV:
  927.       case GL_MATRIX5_NV:
  928.       case GL_MATRIX6_NV:
  929.       case GL_MATRIX7_NV:
  930.          /* OK, fallthrough */
  931.          break;
  932.       default:
  933.          _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(matrix)");
  934.          return;
  935.    }
  936.  
  937.    switch (transform) {
  938.       case GL_IDENTITY_NV:
  939.       case GL_INVERSE_NV:
  940.       case GL_TRANSPOSE_NV:
  941.       case GL_INVERSE_TRANSPOSE_NV:
  942.          /* OK, fallthrough */
  943.          break;
  944.       default:
  945.          _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(transform)");
  946.          return;
  947.    }
  948.  
  949.    ctx->VertexProgram.TrackMatrix[address / 4] = matrix;
  950.    ctx->VertexProgram.TrackMatrixTransform[address / 4] = transform;
  951. }
  952.