Name
    
    ARB_vertex_program

Name Strings

    GL_ARB_vertex_program

Contributors

    Kurt Akeley
    Allen Akin
    Ben Ashbaugh
    Bob Beretta
    John Carmack
    Matt Craighead
    Ken Dyke
    Steve Glanville
    Michael Gold
    Evan Hart
    Mark Kilgard
    Bill Licea-Kane
    Barthold Lichtenbelt
    Erik Lindholm
    Benj Lipchak
    Bill Mark
    James McCombe
    Jeremy Morris
    Brian Paul
    Bimal Poddar
    Thomas Roell
    Jeremy Sandmel
    Jon Paul Schelter
    Geoff Stahl
    John Stauffer
    Nick Triantos

Contact

    Pat Brown, NVIDIA Corporation (pbrown 'at' nvidia.com)

Notice

    Copyright (c) 2002-2013 The Khronos Group Inc. Copyright terms at
        http://www.khronos.org/registry/speccopyright.html

IP Status

    NVIDIA claims to own intellectual property related to this extension, and
    has signed an ARB Contributor License agreement licensing this
    intellectual property.

    Microsoft claims to own intellectual property related to this extension.

Status

    Complete. Approved by ARB on June 18, 2002

Version

    Last Modified Date:  07/25/07
    Revision:            46

Number

    ARB Extension #26

Dependencies

    Written based on the wording of the OpenGL 1.3 specification and requires
    OpenGL 1.3.

    ARB_vertex_blend and EXT_vertex_weighting affect the definition of this
    extension.

    ARB_matrix_palette affects the definition of this extension.

    ARB_point_parameters and EXT_point_parameters affect the definition of
    this extension.

    EXT_secondary_color affects the definition of this extension.

    EXT_fog_coord affects the definition of this extension.

    ARB_transpose_matrix affects the definition of this extension.

    NV_vertex_program interacts with this extension.

    EXT_vertex_shader interacts with this extension.

Overview

    Unextended OpenGL mandates a certain set of configurable per-vertex
    computations defining vertex transformation, texture coordinate generation
    and transformation, and lighting.  Several extensions have added further
    per-vertex computations to OpenGL.  For example, extensions have defined
    new texture coordinate generation modes (ARB_texture_cube_map,
    NV_texgen_reflection, NV_texgen_emboss), new vertex transformation modes
    (ARB_vertex_blend, EXT_vertex_weighting), new lighting modes (OpenGL 1.2's
    separate specular and rescale normal functionality), several modes for fog
    distance generation (NV_fog_distance), and eye-distance point size
    attenuation (EXT/ARB_point_parameters).

    Each such extension adds a small set of relatively inflexible
    per-vertex computations.

    This inflexibility is in contrast to the typical flexibility provided by
    the underlying programmable floating point engines (whether micro-coded
    vertex engines, DSPs, or CPUs) that are traditionally used to implement
    OpenGL's per-vertex computations.  The purpose of this extension is to
    expose to the OpenGL application writer a significant degree of per-vertex
    programmability for computing vertex parameters.

    For the purposes of discussing this extension, a vertex program is a
    sequence of floating-point 4-component vector operations that determines
    how a set of program parameters (defined outside of OpenGL's Begin/End
    pair) and an input set of per-vertex parameters are transformed to a set
    of per-vertex result parameters.

    The per-vertex computations for standard OpenGL given a particular set of
    lighting and texture coordinate generation modes (along with any state for
    extensions defining per-vertex computations) is, in essence, a vertex
    program.  However, the sequence of operations is defined implicitly by the
    current OpenGL state settings rather than defined explicitly as a sequence
    of instructions.

    This extension provides an explicit mechanism for defining vertex program
    instruction sequences for application-defined vertex programs.  In order
    to define such vertex programs, this extension defines a vertex
    programming model including a floating-point 4-component vector
    instruction set and a relatively large set of floating-point 4-component
    registers.

    The extension's vertex programming model is designed for efficient
    hardware implementation and to support a wide variety of vertex programs.
    By design, the entire set of existing vertex programs defined by existing
    OpenGL per-vertex computation extensions can be implemented using the
    extension's vertex programming model.

Issues

    (1) What should this extension be called?

      RESOLVED:  ARB_vertex_program.  DirectX 8 refers to its similar
      functionality as "vertex shaders".  This is a confusing term because
      shaders are usually assumed to operate at the fragment or pixel level,
      not the vertex level.

      Conceptually, what the extension defines is an application-defined
      program (admittedly limited by its sequential execution model) for
      processing vertices so the "vertex program" term is more accurate.

      Some of the API machinery in this extension for describing programs
      should be useful for extending other OpenGL operations with programs
      (though other types of programs may look very different from vertex
      programs).

    (2) What terms are important to this specification?

      vertex program mode - When vertex program mode is enabled, vertices are
      transformed by an application-defined vertex program.

      conventional GL vertex transform mode - When vertex program mode is
      disabled (or the extension is not supported), vertices are transformed
      by GL's conventional texgen, lighting, and transform state.

      vertex program - An application-defined program used to transform
      vertices when vertex program mode is enabled.

      program target - A type or class of program.  This extension supports
      the VERTEX_PROGRAM_ARB target.  Future extensions may add other program
      targets.

      program object - An object maintained internal to OpenGL that
      encapsulates a program and a set of associated state.  Operations
      performed on program objects include loading a program, binding,
      generating program object names, querying state, and deleting.

      program name - Each program object has an associated unsigned integer,
      called the program name.  Applications refer to a program object using
      the program name.

      current program - Each program target may have a current program object.
      For vertex programs, the current program is executed whenever a vertex
      is specified when vertex program mode is enabled.

      default program - Each program target has a default program object,
      referred to using a program name of zero.  The current program for each
      program target is initially the default program for that target.

      program execution environment - A set of resources, instructions, and
      semantic rules used to execute a program.  Each program target may
      support one or more execution environment -- new execution environments
      may provide new instructions, resources, or execution rules.  Program
      strings must specify the execution environment that should be used to
      execute the program.

      program options - An optional feature that modifies the rules of the
      execution environment.  Vertex programs specify the options that they
      require at the beginning of the program.

      vertex attribute - GL state associated with vertices that can vary per
      vertex.

      conventional vertex attributes - Per-vertex attributes used in
      conventional GL vertex transform mode, including colors, normals,
      texture coordinate sets.

      generic vertex attributes - An array of 16+ 4-component vectors added by
      this extension.  Generic vertex attributes can be used by vertex
      programs but are unused in conventional GL vertex transform mode.

      program parameter - A set of constants that are available for vertex
      programs to use during their execution.  Program parameters include
      program environment parameters, program local parameters, conventional
      GL state, and program constants.

      program environment parameter - A set of 96+ 4-component vectors
      belonging to the GL context that can be used as constants during the
      execution of any vertex program.

      program local parameter - A set of 96+ 4-component vectors belonging to
      a vertex program object that can be used as constants during the
      execution of the corresponding vertex program.  Program local parameters
      can not be used by any other vertex programs.

      program constants - Constants declared in the text of a program may be
      used during the execution of that program.

      program temporaries - A set of 12+ 4-component vectors to hold temporary
      results that can be read or written during the execution of a vertex
      program.

      program address registers - A set of 1+ 1-component integer vectors that
      can be used to perform variable indirect accesses to program parameter
      arrays during the execution of a vertex program.  Address registers are
      specified as vectors to allow for future extensions supporting multiple
      address register components.

      program results - A set of 4-component vectors to hold the final results
      of a vertex program.  The program results correspond closely to the set
      of vertex attributes used during primitive assembly and rasterization.
      
      program variables - Variable names used to identify a specific vertex
      attribute, program parameter, temporary, address register, or result.

      program binding - A program statement that declares a variable and
      associates it with a specific vertex attribute, program parameter, or
      program result.

      implicit binding - When an executable instruction refers to a specific
      vertex attribute, program parameter, program result, or constant by
      name, without using an explicit program binding statement.  When such
      values are encountered, an implicit binding to an anonymous variable
      name is created.

      program invocation - The act of implicitly or explicitly kicking off
      program execution.  Vertex programs are invoked automatically when
      vertex program mode is enabled and vertices are received.  Vertex
      programs are also invoked automatically when the current raster position
      is specified.

    (3) What part of OpenGL do vertex programs specifically bypass?

      Vertex programs bypass the following OpenGL functionality:

        - The modelview and projection matrix vertex transformations.

        - Vertex weighting/blending (ARB_vertex_blend).

        - Normal transformation, rescaling, and normalization.

        - Color material.

        - Per-vertex lighting.

        - Texture coordinate generation and texture matrix transformations.

        - Per-vertex point size computations in ARB/EXT_point_parameters

        - Per-vertex fog coordinate computations in EXT_fog_coord and
          NV_fog_distance.

        - Client-defined clip planes.

        - The normalization of AUTO_NORMAL evaluated normals

        - All of the above, when computing the current raster position.

      Operations not subsumed by vertex programs

        - Clipping to the view frustum.

        - Perspective divide (division by w).

        - The viewport transformation.

        - The depth range transformation.

        - Front and back color selection (for two-sided lighting and
          coloring).

        - Clamping the primary and secondary colors to [0,1].

        - Primitive assembly and subsequent operations.

        - Evaluators (except the AUTO_NORMAL normalization).

    (5) This extension adds a set of generic vertex attributes to the existing
    conventional attributes.  The sum of the number of generic and
    conventional attributes supported on a given platform may exceed the total
    number of per-vertex attributes supported in hardware.  How should this
    situation be handled?

      RESOLVED:  Implementations may alias conventional and generic vertex
      attributes, where pairs of conventional and generic vertex attributes
      share the same storage.  Such aliasing will effectively reduce the
      number of vertex attributes a hardware platforms.  While implementations
      may alias attributes, that behavior is not required.  To accommodate both
      behaviors, changing a generic vertex attribute leaves the corresponding
      conventional attribute undefined, and vice versa.

      This undefined behavior is a compromise between the existing
      EXT_vertex_shader extension (which does not permit aliasing) and the
      NV_vertex_program extension (which requires aliasing).  The mapping
      between generic and conventional vertex attributes is found in Table X.1
      below.  This mapping is taken from the NV_vertex_program specification
      and generalized to define behavior for >8 texture coordinate sets.

      Applications that mix conventional and generic vertex attributes in a
      single rendering pass should be careful to avoid using attributes that
      may alias.  To limit inadvertent use of such attributes, loading a
      vertex program that used a pair of attributes that may alias is
      guaranteed to fail.  Applications requiring a small number of generic
      vertex attributes can always safely use generic attributes 6 and 7, and
      any supported attributes corresponding to unused or unsupported texture
      units.  For example, if an implementation supports only four texture
      units, generic attributes 12 through 15 can always be used safely.

    (6) Should there be a "VertexAttribs" entry point to specify multiple
    vertex attributes in one immediate mode call.

      RESOLVED:  No.  Not providing such functionality serves to reduce the
      already large number of required immediate mode entry points.  A
      "VertexAttribs" command would improve the efficiency of vertex attribute
      transfer, but vertex arrays or display lists should still be better.

    (7) Should a full complement of data types (signed and unsigned bytes,
    shorts, and ints, as well as floats and doubles) be supported for vertex
    attributes?  Should fixed-point data types be supported in both normalized
    (map the range to [0,1] or [-1,1]) and unnormalized form?

      RESOLVED:  For vertex arrays, all data type combinations are supported.

      For immediate mode, a smaller subset is supported, to limit the number
      of immediate-mode entry points added by this extension.  In fully
      general form, 112 immediate-mode entry points (4 sizes x 2
      vector/non-vector x 14 data types) would be required.

      Immediate mode support is available for non-normalized shorts, floats,
      and doubles for all component counts.  Additionally, immediate mode
      support is available for 4-component vectors of all data types
      (normalized and unnormalized).

      Note also that in immediate mode, the "N" qualifier in function names
      like VertexAttrib4Nub will be used to indicate that fixed-point data
      should be normalized.

    (8) How should applications indicate that fixed-point generic vertex
    attribute array components should be converted to [-1,+1] or [0,1] ranges?

      RESOLVED:  The function VertexAttribPointerARB takes a boolean argument
      <normalized> that indicates whether fixed-point array data should be
      normalized to [-1,+1] or [0,1].  

      One alternate approach would have been to extend to set of enumerants to
      include values such as NORMALIZED_UNSIGNED_BYTE_ARB.  Adding such
      enumerants in some sense implies that UNSIGNED_BYTE is not normalized,
      even though it usually is.

    (9) In unextended OpenGL, calling Vertex() specifies a vertex and causes
    vertex transformation operations to be performed on the vertex.  Should
    there be an equivalent method to specify a vertex using generic vertex
    attributes?  If so, how should this be accomplished?

      RESOLVED:  Setting generic vertex attribute zero will always specify a
      vertex.  Vertex*(...) and VertexAttrib*(0,...) are specified to be
      equivalent, whether or not vertex program mode is enabled.  Allowing
      generic vertex attribute zero to specify a vertex allows applications to
      write vertex programs that use only generic attributes; otherwise,
      applications would have had to use Vertex() to provoke vertex
      processing.

    (10) How is this extension different from previous vertex program
    extensions, such as EXT_vertex_shader or NV_vertex_program?  What pitfalls
    are there in porting vertex programs to/from this extension?
    
      RESOLVED:  See "Interactions with NV_vertex_program" and "Interactions
      with EXT_vertex_shader" sections near the end of this specification.  

    (11) Should program parameter variables bound to GL state be updated
    automatically after the bound state changes?  If so, when?

      RESOLVED:  Yes.  Such variables are updated automatically prior to the
      next vertex program invocation with no application intervention
      required.  A proposal to reduce the burden by requiring a manual "update
      state" step was considered and rejected.

    (12) How should this specification handle variable bindings to Material
    state?  Material is allowed inside a Begin/End, so material properties are
    technically per-vertex state.

      RESOLVED:  Materials can be bound only as program parameters.  Changes
      to material properties inside a Begin/End will leave the bindings
      undefined until the subsequent End command.  At that point, all material
      property bindings are guaranteed to be updated, and any material
      property changes up to the next Begin command are guaranteed to take
      effect immediately.

      Supporting per-vertex material properties places additional pressure on
      the number of per-vertex bindings an implementation can support, which
      was already a problem.  See issue (5).  

      In practice, material properties are usually not changed in this manner.
      Applications needing to change material properties inside a Begin/End in
      vertex program mode can work around this limitation by storing the color
      in a conventional or generic vertex attribute and modifying the vertex
      program accordingly.

    (13) What semantic restrictions, if any, should be imposed on binding the
    same GL state to multiple variables?  The grammar permits such bindings,
    but allowing this behavior means that single state updates must update
    multiple variables.

      RESOLVED:  Cases where a single state update necessarily requires
      updating multiple variables are disallowed.  The only restriction
      resulting from this decision is that a single state variable can not be
      bound more than once in the collection of arrays that are accessed using
      relative addressing (at run time).  The driver can and will coalesce all
      other bindings accessed only at fixed offsets into a single binding.

      This restriction and a little driver work allows the same state variable
      to be used multiple times without requiring that a single state change
      update multiple variables.

    (14) What semantic restrictions, if any, should be imposed on using
    multiple vertex attributes or program parameters in the same instruction?

      RESOLVED:  None.  If the underlying hardware implementation does not
      support reads of multiple attributes or program parameters, the driver
      may need to transparently insert additional instructions and/or consume
      temporaries to perform the operation.
    
    (15) How and when should related state be combined into a single program
    parameter binding?  Additionally, should any values derived from core GL
    state be exposed, too?

      RESOLVED:  Related state should be combined when possible, as long as
      the binding name remains somewhat sensible.  Additionally, certain
      pre-computed state items useful for performance reasons are also
      exposed.  In particular, the following GL state combinations are
      supported:

        * Light attenuation constants and the spot light exponent are combined
          into a single vector called "state.light[n].attenuation" (spot
          lights can attenuate the lit result).

        * Spot light direction and cutoff angle cosine are called
          "state.light[n].spot.direction" (cutoff is directional information).
          Binding the cutoff angle itself is pretty useless, so the cosine is
          used.

        * A pre-computed half angle for lighting with infinite lights and an
          infinite viewer is provided and called "state.light[n].half".

        * Pre-computed products of ambient, diffuse, and specular light colors
          with the corresponding front or back material colors are supported,
          and are called "state.lightprod[n].<face>.<property>".

        * Exponential fog density, linear fog start and end parameters, as
          well as the pre-computed reciprocal of (end-start) are combined into
          one vector called "state.fog.params".

        * The core point size, minimum and maximum size clamps
          (ARB_point_parameters), and multisample fade size threshold
          (ARB_point_parameters) are combined into a single vector called
          "state.point.size".

        * Precomputed transpose, inverse, and inverse transpose matrices are
          supported for each base matrix type.

    (16) Should the initial values of temporaries and results be undefined?

      RESOLVED:  Since the underlying hardware differs, it was decided to
      leave these values uninitalized.  There are a few issues related to this
      behavior that programs should keep in mind:

        * Since any results not written by the program are undefined, programs
          should write to all result registers that are needed during
          rasterization.

        * In particular, the initial vertex position result is undefined, and
          will remain undefined if not written by a program.  To achieve
          proper results, vertex programs should be careful to write to all
          four components of the vertex position.  Otherwise, primitives may
          be completely clipped or produce undefined results during
          rasterization.  There is no semantic requirement that programs must
          write a transformed vertex position, so erroneous programs will load
          succesfully, but will produce undefined (and probably useless)
          results.  Such a semantic requirement may be impossible to enforce
          in future language versions that support run-time branching.

        * Since vertex programs may be executed when the raster position is
          set, any attributes not written by the program will result in
          undefined state in the current raster position.  Programs should
          write to all result registers that would be used when rasterizing
          pixel primitives using the current raster position.

        * If conventional OpenGL texture mapping operations are performed, a
          program should always write to the "w" coordinate of any texture
          coordinates result registers it needs to use.  Conventional OpenGL
          texture accesses always use projective texture coordinates (e.g.,
          s/q, t/q, r/q), even though q is almost always 1.0.  An undefined q
          coordinate (coming from the "w" component of the result register)
          may produce undefined coordinates on the texture lookup.

    (17) Should vertex programs be required to have a header token and an end
    token?

      RESOLVED:  Yes.  The header token for this extension is named
      "!!ARBvp1.0".  The ARB may standardize future language versions which
      would be expected to have tokens like "!!ARBvp2.0".  Vertex programs
      must end with the "END" token.

      The initial header token reminds the programmer what type of program
      they are writing.  If vertex programs are ever read from disk files, the
      header token can be used to specifically identify vertex programs.  The
      initial header tokens will also make it easier for programmers to
      distinguish between multiple types of vertex programs and between vertex
      programs and another future type of programs.

      We expect that programs may be generated by concatenation of program
      fragments.  The "END" token will hopefully reduce bugs due to specifying
      an incorrectly concatenated program.

    (18) Should ProgramStringARB take a <program> specifier?  Should
    ProgramLocalParameterARB and GetProgramLocalParameterARB take a <program>
    specifier?  How about GetProgramivARB and GetProgramStringARB?

      RESOLVED:  No to all.  Instead, these calls are specified to always
      query or modify the currently bound program object.  Using bound objects
      allows GL implementations to avoid locking and name lookup overhead on
      each such call.

      This behavior does imply that applications loading a sequence of program
      objects must bind each in turn.

    (19) Should relative addressing be performed using an address register
    (load up an integer register) or by taking a floating-point scalar?

      RESOLVED:  Address register.  It would not be a good idea to support
      both syntaxes simultaneously, since using a floating-point scalar may
      consume the only available address register in the process.  The current
      address register syntax can be easily extended to allow for multiple
      integer registers and/or enable other integer operations in a later
      extension.

      Using a floating-point index may require an extra instruction on some
      architectures, and would require optimization work to eliminate
      redundant loads.  Using a floating-point index may consume one of a
      small number of temporary registers.  On the other hand, for
      implementations without a dedicated address register, it may be
      necessary to dedicate a general-purpose register (or register component)
      to hold the address register contents.

    (20) How should user-defined clipping be supported in this specification?

      RESOLVED:  User-defined clipping is not supported in standard vertex
      program mode.  User-defined clipping support will be provided for
      programs that use the "position invariant" option, where all vertex
      transformation operations are performed by the fixed-function pipeline.
      
      It is expected that future vertex program extensions or a future
      language standard may provide more powerful user clipping functionality.

      The options considered were:

      (1) Not at all.  Does not work for applications requiring user clipping.
          User clipping could be supported through a language extension.

      (2) Support only through the "position_invariant" option, where vertex
          transformation is performed by the fixed-function pipeline.

      (3) Support by using the fixed-function pipeline to generate eye
          coordinates and perform user clipping as specified for conventional
          transformation.  May not work properly if the vertex transformation
          doesn't match the standard "multiply by modelview and projection
          matrices" model.
  
      (4) Project existing fixed-function clip planes into clip coordinates
          and perform the clip test in clip space.  The clip planes would be
          transformed by the inverse of the projection matrix, which will not
          work if the projection matrix is singular.

      (5) Provide a 4-component "user clip coordinate" result that can be
          bound by a vertex program.  User clipping is performed as in
          unextended OpenGL, using the "user clip coordinate" in place of the
          non-existant eye coordinates.  This approach allows an application
          to do user clipping in any coordinate system.  Clipping would not be
          independent of primitive tesselation as in the conventional
          pipeline.  Additionally, the implicit transformation of specified
          clip planes by the modelview matrix may be undesirable (e.g.,
          clipping in object coordinates).

      (6) Provide one or more "clip plane distance" results that can be bound
          by a vertex program.  For conventional clipping applications, vertex
          programs would compute the dot products normally computed by
          fixed-function hardware.  Additionally, this method would enable
          additional unconventional clipping effects.  Primitives would be
          clipped to the portion whose interpolated clip distances are greater
          than or equal to zero.  This approach has the same issues as (5).

    (21) How should future vertex program opcodes be named?

      RESOLVED:  Three-character names are recommended for brevity.  Three
      character names are not a hard-and-fast requirement; extra characters
      may be needed for clarity or to disambiguate instructions.

    (22) Should anything be said about the precision used for carrying out the
    instructions?

      RESOLVED:  Not much; precision will vary across platforms.  The minimum
      precision requirements (1 part in 10^5 or roughly 17 bits) are spelled
      out in section 2.1.1.  In practice, implementations will generally
      provide precision comparable to that obtained using single precision
      floats.  Documenting exact precision across implementations is
      difficult.  Additionally, it is difficult to spell out precision
      requirements for "compound" operations such as DP4.

    (23) Should this extension support evaluator maps for generic vertex
    attributes?  If so, what attribute sizes should be supported?  Note that
    such maps are not supported at all for texture units except zero.

      RESOLVED:  No.  Evaluator support has not been consistently extended in
      previous extensions.  For example, neither ARB_multitexture nor OpenGL
      1.3 provide support for evaluators for texture units other than unit
      zero.  Adding evaluators for generic attributes involves a large amount
      of new state and complexity, particularly if evaluators should be
      supported in general form (1, 2, 3, and 4 components, all supported data
      type).

    (25) The number of generic vertex attributes is implementation-dependent
    and is at least 16.  Each generic vertex attribute has a vertex array
    enable.  Should two new entry points be provided to accept an arbitrary
    attribute number, or should we reserve a range of enumerants that is
    "large enough"?

      RESOLVED:  Yes.  EnableVertexAttribArrayARB and
      DisableVertexAttribArrayARB.  This allows the number of vertex
      attributes to be unbounded, instead of using a limited range.

    (26) What limits should be imposed on the constants that can be added to
    or subtracted from the address register for relative addressing?  Negative
    offsets are sometimes useful for shifting down in an array.

      RESOLVED:  -64 to +63 should be sufficient for the time being.  Offset
      sizes are limited to allow offsets to be baked into device-dependent
      instruction encodings.

    (28) What level of precision should be guaranteed for the EXP and LOG
    instructions?  And for the EX2 and LG2 instructions?

      RESOLVED:  The low precision EXP and LOG instructions should give at
      least 10 bits (2^-11 maximum relative error).  No specific treatment
      will be added for EX2/LG2, implying that the computations should at
      least meet the minimal floating-point precision required by the spec.

    (29) Should incremental program compilation be supported?

      RESOLVED:  No.  Applications can compile programs just as easily using
      string concatenation.

    (30) Should the execution environment be identified by the program itself
    or as an additional "language" parameter to ProgramStringARB?

      RESOLVED:  Programs should identify their execution environment in the
      header.  The header (plus any specified options) make it clear what kind
      of program is being defined.

    (31) Should this extension provide support for character sets other than
    7-bit ASCII?

      RESOLVED:  Provide a <format> argument to ProgramStringARB to allow for
      future extensions.  Only ASCII will be supported by this extension;
      additional character sets or encodings could be supported using separate
      extensions.

    (32) Support for "program object" functionality may be applicable to
    future program targets.  Should this functionality be factored out into a
    separate extension?

      RESOLVED:  No, such separation is not necessary.  This extension was
      designed to allow to easily accommodate future program target types.  It
      would be straightforward to put program object functionality into a
      separate extension, but the functionality provided by that extension
      would be of no value by itself.

    (33) Should program residency management be supported?

      RESOLVED:  No.  This functionality can be supported in a separate
      extension if desired.  If may be desirable to address residency
      management in a more general form, where an application may desire a
      diverse set of objects (textures, programs) to be resident at once.

    (34) Should program object management APIs (GenProgramsARB,
    DeleteProgramsARB) work like texture objects or display lists?

      RESOLVED:  Texture objects.  

      Both approaches have their merits.  Pluses for the display list model
      include:  no need to keep around multiple indices if you want to
      allocate a group of object, contiguous indices may fall out on
      implementations that share one block allocator for textures and display
      lists.  Pluses for the texture object model:  non-contiguous indices may
      be more optimizable -- new objects can be mapped to empty blocks in a
      hash table to avoid collisions with existing objects, separate indices
      are more compatible with a future handle-based object paradigm, and a
      larger base of extensions using this model.  Note that display list
      allocations needed to be contiguous to support CallLists, but no such
      requirement for texture or program objects exists for programs.

    (35) Should there be support for a program object zero?  With texture
    objects, texture object zero is "special" because it is the default
    texture object for each target type.  Is there something like this for
    program objects?

      RESOLVED:  Yes.  Like texture objects, there should be a separate
      program object zero for each program type.  This allows applications to
      use vertex programs without needing to generate and manage program
      objects.

      With texture objects, an object zero was needed for backward
      compatibility with pre-OpenGL 1.1 applications.  There is no such
      requirement here, but providing an object zero nicely matches the
      familiar texture object model.

    (36) How should this extension provide feedback on why a program failed to
    load?

      RESOLVED:  Two queries are provided.  Calling GetIntegerv() with
      PROGRAM_ERROR_POSITION_ARB provides the offset of an offending
      instruction in the program string.  An error position of -1 indicates
      that a program loaded successfully.  Calling GetString() with
      PROGRAM_ERROR_STRING_ARB returns an implementation-dependent error
      string explaining the reason for the failure.  The error string can be
      queried even on successful program loads to check for warning messages.

      The error string may be kept in a static buffer managed by the GL
      implementation.  Implementations may reuse the same buffer on subsequent
      calls to ProgramStringARB, so returned error strings are guaranteed to
      be valid only until the next such call.

    (37) How does ARB_vertex_blend's WEIGHT_SUM_UNITY_ARB mode interact with
    this extension?  This mode allows an application to specify N-1 weights,
    and have the Nth weight computed by the GL.

      RESOLVED:  The ARB_vertex_blend spec (as of May, 2002) specifies that
      the nth weight is automatically computed by the GL and is effectively
      current state.  In practice, ARB_vertex_blend implementations compute
      the nth weight on the fly in the fixed-function transformation pipeline,
      implying that the ARB_vertex_blend spec may require a fix.  For the
      purposes of this extension, the WEIGHT_SUM_UNITY_ARB enable is ignored
      in vertex program mode.  Applications performing a vertex weighting
      operation in a vertex program are free to compute the extra weight in
      the program.

    (38) Should program environment parameters be pushed and popped?

      RESOLVED:  No.  There is no need to push and pop this large set of
      state, much like pixel maps.  Adding a new attribute bit would have
      complicated logistics (would the bit be included in ALL_ATTRIB_BITS?).
      Having program local parameters provides a method for making localized
      changes to certain state simply by switching programs.

    (39) How should this extension interact with color material?

      RESOLVED:  When color material is enabled, any bindings of material
      colors that track the current color should be updated when the current
      color is updated.  In this specification, material properties can be
      bound only as program parameters, and any changes to the material
      properties inside a Begin/End leave the bindings undefined until the
      next End command.  Similarly, any indirect changes to the material
      properties (through ColorMaterial) will have a similar effect.

      Several other options were considered here.  One option was to support
      per-vertex material property bindings and have programs that reference
      tracked material properties should get the current color.  This could be
      handled either by broadcasting the current color to multiple vertex
      attributes, or recompiling the vertex program so that references to a
      tracked material property are redirected to the vertex color.  Both such
      solutions are somewhat complex.  A second option would be to ignore the
      COLOR_MATERIAL enable and instead use an "old" material color.  This
      breaks the standard color material model.  Implementations can and often
      do defer such updates (making an "old" color available), some conditions
      may cause an implementation to update of material state at odd times.

    (41) What about when the execution environment involves support for other
    extensions?  In particular, the execution environment subsumes some
    functionality from EXT/ARB_point_parameters, EXT_fog_coord,
    EXT_secondary_color, and ARB_multitexture.

      RESOLVED:  This extension assumes support for functionality that
      includes a fog coordinate, secondary color, per-vertex point sizes, and
      multiple texture coordinates (at least to the extent that it exposes >1
      texture coordinate).  All of these extensions are supported fairly
      widely.  On some platforms, some of this functionality may require
      software fallbacks.

    (42) How does PointSize work with vertex programs?

      RESOLVED:  If VERTEX_PROGRAM_POINT_SIZE_ARB is disabled, the size of
      points is determined by the PointSize state and is not attenuated, even
      if EXT_point_parameters is supported.  If enabled, the point size is the
      point size result value, and is clamped to implementation-dependent
      point size limits during point rasterization.

    (43) What do we say about the alpha component of the secondary color?

      RESOLVED:  The alpha component of the secondary color has generally been
      treated as zero.  This extension specifies that only the R, G, and B
      components are added in the color sum operation, making the alpha
      component of the secondary color irrelevant.  Other downstream
      extensions may allow applications to make use of this component.

    (44) How are edge flags handled?

      RESOLVED:  Edge flags are passed through without the ability to be
      modified by a vertex program.  Applications are free to send edge flags
      when vertex program mode is enabled.

    (45) Should programs be C-style null-terminated strings?
      
      RESOLVED:  No.  Programs should be specified as an array of GLubyte with
      an explicit length parameter.  OpenGL has no precedent for passing
      null-terminated strings into the API (though GetString returns
      null-terminated strings).  Null-terminated strings may be problematic
      for some programming languages.

    (46) Should all existing OpenGL transform functionality and extensions be
    implementable as vertex programs?

      RESOLVED:  Yes.  Vertex programs should be a complete superset of what
      you can do with OpenGL 1.2 and existing vertex transform extensions.  To
      implement EXT_point_parameters, the VERTEX_PROGRAM_POINT_SIZE_ARB enable
      is introduced.  To implement two-sided lighting, the
      VERTEX_PROGRAM_TWO_SIDE_ARB enable is introduced.  To implement color
      material, applications should refer to the per-vertex color attribute in
      their vertex programs.

    (47) Should there be a plural version of ProgramEnvParameter and
    ProgramLocalParameter, which would set multiple parameters in a single
    call?

      RESOLVED:  No; not necessary.

    (48) Can the currently bound vertex program object be deleted or reloaded?

      RESOLVED:  Yes.  When ProgramStringARB is called to reload a program
      object, subsequent program executions will use the new program.  When
      DeleteProgramsARB deletes a currently bound program object, object zero
      becomes the new current program object.

    (49) What happens if you transform vertices in vertex program mode, but
    the current program object does not contain a valid vertex program?

      RESOLVED:  Begin will fail with an INVALID_OPERATION error if the
      currently bound vertex program object does not have a valid program.
      The same applies to RasterPos and any command (Rect, DrawArrays,
      DrawElements) that implies a Begin.

      Because Vertex is ignored outside of a Begin/End pair (without
      generating an error) it is impossible to provoke a vertex program if the
      current vertex program object is nonexistent or invalid.  Other
      per-vertex parameters (for examples those set by Color, Normal, and
      VertexAttrib*ARB when the attribute number is not zero) are allowed
      since they are legal outside of a Begin/End.

    (50) Discussing matrices is confusing because of row-major versus
    column-major issues.  Can you give an example of how a matrix is bound?

      RESOLVED:  Assume program matrix zero were loaded with the following
      code:
 
        // When loaded, the first row is "1, 2, 3, 4", because of column-major
        // (OpenGL spec) vs. row-major (C) differences.
        GLfloat matrix[16] = { 1, 5, 9,  13,
                               2, 6, 10, 14,
                               3, 7, 11, 15,
                               4, 8, 12, 16 };
        glMatrixMode(GL_MATRIX0_ARB);
        glLoadMatrixf(matrix);

      Then in the program

        !!ARBvp1.0
        PARAM mat1[4] = { state.matrix.program[0] };
        PARAM mat2[4] = { state.matrix.program[0].transpose };

      mat1[0] would have (1,2,3,4), mat1[3] would have (13,14,15,16), mat2[0]
      would have (1,5,9,13), and mat2[3] would have (4,8,12,16).

    (51) Should the new vertex program-related enables push/pop with
    ENABLE_BIT?

      RESOLVED:  Yes.  Pushing and popping enable bits is easy.

    (52) Should all the vertex attribute state push/pop with CURRENT_BIT?

      RESOLVED:  Yes.

    (53) Should all the vertex attrib vertex array state push/pop with
    CLIENT_VERTEX_ARRAY_BIT?

      RESOLVED:  Yes.

    (55) Should we generate an INVALID_VALUE operation if updating a vertex
    attribute greater than MAX_VERTEX_ATTRIBS_ARB?

      RESOLVED:  Yes.  The other option would be to leave the behavior
      undefined, as with MultiTexCoord() functions.  An implementation could
      mask or modulo the vertex attribute index with MAX_VERTEX_ATTRIB_ARB if
      it were a power of two.  This error check will be a minor performance
      issue with VertexAttrib*ARB() and VertexAttribArrayARB() calls.  There
      will be no per-vertex overhead when using vertex arrays or display
      lists.

    (56) Should writes to program environment or local parameters during a
    vertex program be supported?

      RESOLVED.  No.  Writes to program parameter registers from within a
      vertex program would require the execution of vertex programs to be
      serialized with respect to each other.  This would create a severe
      implementation penalty for pipelined or parallel vertex program
      execution implementations.

    (58) Should program objects be shared among rendering contexts in the same
    manner as display lists and texture objects?

      RESOLVED:  Yes.

    (60) Should there be a MatrixMode or ActiveTexture-style selector for
    vertex attributes?

      RESOLVED:  No.  While this would reduce the number of enumerants used by
      this extensions, it would create programming a hassle in lots of cases.
      Consider having to change the vertex attribute mode to enable a set of
      vertex arrays.

    (61) How should queries of vertex attribute arrays work?

      RESOLVED:  Add new get commands.  Using the existing calls would require
      adding 6 sets of 16+ enumerants for current state and vertex attribute
      array state.  That's too many new enumerants.  Instead, add
      GetVertexAttribARB and GetVertexAttribPointervARB.  GetVertexAttribARB
      will be used to query vertex attribute array state and the current
      values of the generic vertex attributes.  Get and GetPointerv will not
      return vertex attribute array state and pointers.

    (63) What should be said about rendering invariances?

      RESOLVED:  See the Appendix A additions below.

      The justification for the two rules cited is to support multi-pass
      rendering when using vertex programs.  Different rendering passes will
      likely use different programs so there must be some means of
      guaranteeing that two different programs can generate particular
      identical vertex results between different passes.

      In practice, this does limit the type of vertex program implementations
      that are possible.

      For example, consider a limited hardware implementation of vertex
      programs that uses a different floating-point implementation than the
      CPU's floating-point implementation.  If the limited hardware
      implementation can only run small vertex programs (say the hardware
      provides on 4 temporary registers instead of the required 12), the
      implementation is incorrect and non-conformant if programs that only
      require 4 temporary registers use the vertex program hardware, but
      programs that require more than 4 temporary registers are implemented by
      the CPU.

      This is a very important practical requirement.  Consider a multi-pass
      rendering algorithm where one pass uses a vertex program that uses only
      4 temporary registers, but a different pass uses a vertex program that
      uses 5 temporary registers.  If two programs have instruction sequences
      that given the same input state compute identical resulting vertex
      positions, the multi-pass algorithm should generate identically
      positioned primitives for each pass.  But given the non-conformant
      vertex program implementation described above, this could not be
      guaranteed.

      This does not mean that schemes for splitting vertex program
      implementations between dedicated hardware and CPUs are impossible.  If
      the CPU and dedicated vertex program hardware used IDENTICAL
      floating-point implementations and therefore generated exactly identical
      results, the above described could work.

      While these invariance rules are vital for vertex programs operating
      correctly for multi-pass algorithms, there is no requirement that
      conventional OpenGL vertex transform mode will be invariant with vertex
      program mode.  A multi-pass algorithm should not assume that one pass
      using vertex program mode and another pass using conventional GL vertex
      transform mode will generate identically positioned primitives.

      Consider that while the conventional OpenGL vertex program mode is
      repeatable with itself, the exact procedure used to transform vertices
      is not specified nor is the procedure's precision specified.  The GL
      specification indicates that vertex coordinates are transformed by the
      modelview matrix and then transformed by the projection matrix.  Some
      implementations may perform this sequence of transformations exactly,
      but other implementations may transform vertex coordinates by the
      composite of the modelview and projection matrices (one matrix transform
      instead of two matrix transforms in sequence).  Given this
      implementation flexibility, there is no way for a vertex program author
      to exactly duplicate the precise computations used by the conventional
      OpenGL vertex transform mode.

      The guidance to OpenGL application programs is clear.  If you are going
      to implement multi-pass rendering algorithms that require certain
      invariances between the multiple passes, choose either vertex program
      mode or the conventional OpenGL vertex transform mode for your rendering
      passes, but do not mix the two modes.

    (64) Should there be a way to guarantee position invariance with respect
    to conventional vertex transformation?

      RESOLVED:  Yes.  The "OPTION ARB_position_invariant" program option
      addresses this issue.  This program option will be available on all
      implementations of this extension.

      John Carmack advocated the need for this.

    (65) Why must RCP of 1.0 always be 1.0?

      RESOLVED:  This is important for 3D graphics so that non-projective
      textures and orthogonal projections work as expected.  Basically when q
      or w is 1.0, things should work as expected.  Stronger requirements such
      as "RCP of -1.0 must always be -1.0" are encouraged, but there is no
      compelling reason to state such requirements explicitly as is the case
      for "RCP of 1.0 must always be 1.0".

    (66) What happens when the source scalar value for the ARL instruction is
    an extremely large positive or negative floating-point value?  Is there a
    problem mapping the value to a constrained integer range?

      RESOLVED:  In this extension, address registers are only useful for
      relative addressing.  The range of offsets that can be added to an
      address register is limited (-64 to +63) and the set of valid array
      indices is also limited to MAX_PROGRAM_PARAMETERS_ARB.  So, the set of
      floating-point values that needs to be handled properly is
      well-constrained.

    (67) How do you perform a 3-component normalize in three instructions?

      RESOLVED:  As follows.

        DP3 result.w, vector, vector;     # result.w = nx^2+ny^2+nz^2
        RSQ result.w, result.w;           # result.w = 1/sqrt(nx^2+ny^2+nz^2)
        MUL result.xyz, result.w, vector;

    (69) How do you compute the determinant of a 3x3 matrix in three
    instructions?

      RESOLVED:  As follows.

        #
        # Determinant of | vec0.x  vec0.y  vec0.z | into result.
        #                | vec1.x  vec1.y  vec1.z |
        #                | vec2.x  vec2.y  vec2.z |
        #
        MUL result, vec1.zxyw, vec2.yzxw;
        MAD result, vec1.yzxw, vec2.zxyw, -result;
        DP3 result, vec0, result;

    (70) How do you transform a vertex position by a 4x4 matrix and then
    perform a homogeneous divide?

      RESOLVED:  As follows.

        ATTRIB  pos = vertex.position;
        TEMP    result, temp;
        PARAM   mat[4] = { state.matrix.modelview };

        DP4     result.w, pos, mat[3];
        DP4     result.x, pos, mat[0];
        DP4     result.y, pos, mat[1];
        DP4     result.z, pos, mat[2];
        RCP     temp.w, result.w;
        MUL     result, result, temp.w;

    (71) How do you perform a vector weighting of two vectors using a single
    weight?

      RESOLVED:  As follows.

        # result = a * vec0 + (1-a) * vec1
        #        = vec1 + a * (vec0 - vec1)
        SUB result, vec0, vec1;
        MAD result, a, result, vec1;

    (72) How do you reduce a value to some fundamental period such as 2*PI?

      RESOLVED:  As follows.

        # result = 2*PI * fraction(in/(2*PI))
        # piVec = (1/(2*PI), 2*PI, 0, 0)
        PARAM piVec = { 0.159154943, 6.283185307, 0, 0 };

        MUL result, in, piVec.x;
        EXP result, result.x;
        MUL result, result.y, piVec.y;

    (73) How do you implement a simple ambient, specular, and diffuse infinite
    lighting computation with a single light and an eye-space normal?

      RESOLVED:  As follows.

        !!ARBvp1.0
        ATTRIB iPos         = vertex.position;
        ATTRIB iNormal      = vertex.normal;
        PARAM  mvinv[4]     = { state.matrix.modelview.invtrans };
        PARAM  mvp[4]       = { state.matrix.mvp };
        PARAM  lightDir     = state.light[0].position;
        PARAM  halfDir      = state.light[0].half;
        PARAM  specExp      = state.material.shininess;
        PARAM  ambientCol   = state.lightprod[0].ambient;
        PARAM  diffuseCol   = state.lightprod[0].diffuse;
        PARAM  specularCol  = state.lightprod[0].specular;
        TEMP   xfNormal, temp, dots;
        OUTPUT oPos         = result.position;
        OUTPUT oColor       = result.color;

        # Transform the vertex to clip coordinates.   
        DP4   oPos.x, mvp[0], iPos;
        DP4   oPos.y, mvp[1], iPos;
        DP4   oPos.z, mvp[2], iPos;
        DP4   oPos.w, mvp[3], iPos;

        # Transform the normal to eye coordinates.
        DP3   xfNormal.x, mvinv[0], iNormal;
        DP3   xfNormal.y, mvinv[1], iNormal;
        DP3   xfNormal.z, mvinv[2], iNormal;
        
        # Compute diffuse and specular dot products and use LIT to compute
        # lighting coefficients.
        DP3   dots.x, xfNormal, lightDir;
        DP3   dots.y, xfNormal, halfDir;
        MOV   dots.w, specExp.x;
        LIT   dots, dots;

        # Accumulate color contributions.
        MAD   temp, dots.y, diffuseCol, ambientCol;
        MAD   oColor.xyz, dots.z, specularCol, temp;
        MOV   oColor.w, diffuseCol.w;
        END

    (75) Can you perturb transformed vertex positions with a vertex program?

       RESOLVED: Yes.  Here is an example that performs an object-space
       diffuse lighting computations and perturbs the vertex position based on
       this lighting result.  Do not take this example too seriously.

         !!ARBvp1.0
         #
         # Program environment parameters:
         # c[0].xyz = normalized light direction in object-space
         #
         # outputs diffuse illumination for color and perturbed position
         #
         ATTRIB iPos         = vertex.position;
         ATTRIB iNormal      = vertex.normal;
         PARAM  mvp[4]       = { state.matrix.mvp };
         PARAM  lightDir     = program.env[0];
         PARAM  diffuseCol   = { 1, 1, 0, 1 };
         TEMP   temp;
         OUTPUT oPos         = result.position;
         OUTPUT oColor       = result.color;
 
         DP3   temp, lightDir, iNormal;
         MUL   oColor.xyz, temp, diffuseCol;
         MAX   temp, temp, 0;            # clamp dot product to zero
         MUL   temp, temp, iNormal;      # align in direction of normal
         MUL   temp, temp, 0.125;        # scale displacement by 1/8
         SUB   temp, temp, iPos;         # perturb
         DP4   oPos.x, mvp[0], temp;     # xform using perturbed position
         DP4   oPos.y, mvp[1], temp;
         DP4   oPos.z, mvp[2], temp;
         DP4   oPos.w, mvp[3], temp;
         END

    (76) Should this extension provide any method for updating program
    parameters in a program itself?

      RESOLVED:  No.  NV_vertex_program provided a special mechanism to do
      this using a "vertex state program" manually executed by calling
      ExecuteProgramNV.  This capability has not proven itself particularly
      useful to date.

    (78) Should there be a different ProgramStringARB call for every distinct
    program target?  Arguably, 1D, 2D, and 3D textures each have their own
    TexImage command for specifying their image data.

      RESOLVED:  No.  All program objects can/should be loaded with
      ProgramStringARB.  We expect the string to be a sufficient to express
      any kind of programmability.

      Moreover, the 1D, 2D, and 3D TexImage commands describe the image being
      specified as opposed to the texture target being updated.  With cube map
      textures, there are six face texture targets that use the TexImage2D
      command but not with the TEXTURE_2D target.

    (79) This extension introduces a collection of new matrices for use by
    vertex programs (and possibly other programs as well).  What should these
    matrices be called?

      RESOLVED:  Program matrices.  These matrices are referred to as
      "tracking matrices" in NV_vertex_program, but the functionality is
      equivalent.

    (80) With ARB_vertex_blend and EXT_vertex_weighting, there are multiple
    modelview matrices.  This extension provides a single "MVP" matrix,
    defined to be the product of modelview matrix 0 and the projection
    matrices.  Should this extension instead provide one MVP matrix per
    modelview matrix?

      RESOLVED:  No.  Providing multiple MVP matrices allows applications to
      do N transformations into clip space and then one weighting operation,
      instead of N transformations into eye space, a weighting operation, and
      then a single transformation into clip space.  This would potentially
      save instructions, but this optimization would be of no value if the
      program did any other operations that required eye coordinates.
      
      Note also that the MVP transformations are likely general 4x4 matrix
      multiplies (4 DP4 instructions per transform).  On the other hand,
      object and eye coordinates are often 3D coordinates with a constant W of
      1.0.  So each transformation to eye coordinates may require only 3 DP4
      instructions, in which case the comparison may be 4N instructions (clip
      weighting) vs. 3N+4 (eye weighting).

    (81) Should variable declarations be allowed to be anywhere within the
    program body, or should they instead be required to be done at the
    beginning of the program?  Should the possibility of branching in a future
    standard affect this resolution?

      RESOLVED:  Declarations will be allowed anywhere in the program text;
      the only ordering requirement is that the declaration of a variable must
      precede its use in the program text.  Requiring up-front variable
      declarations may require multiple passes for applications that build
      programs on the fly.

      While declarations can appear anywhere in the program body, they are not
      executable statements.  Any corresponding bindings (including constant
      initializations) are resolved before the program executes.  The bindings
      will be resolved even if a program were to "branch around" a
      declaration.

    (82) Should address register variables be treated as vectors?  If so,
    should a variable number of components (up to four) be supported by this
    extension?

      RESOLVED:  In the future, four-component address vectors may be
      supported, and vector notation is used for forward compatibility.  Using
      this notation makes address registers consistent with all the other
      vector data types in this extension.  However, support for more than one
      usable component will be left for future extensions, but could be added
      via a program option or in a new language revision (e.g., !!ARBvp2.0).

    (83) Should program local parameters be logically connected to the program
    string or the program object?

      RESOLVED:  Program local parameters are properties of a program object.
      Their values persist even after a new program is loaded into the object.
      This model does allow applications to recompile the program in a given
      object based on certain rendering settings without having to
      re-initialize any state stored in the object.

    (84) Should this extension provide a method to specify "anonymous" program
    local parameters and query an index into the program parameter array.

      RESOLVED:  No.  It would be nice to declare a variable in a program such
      as

        PARAM foo = program.local;  # note no index in the array

      after which an application could query the location of "foo" in the
      program local parameter array.  However, given that local parameters
      persist even across program loads, it would be difficult to specify what
      program local parameter "foo" would be assigned to.

    (85) EXT_vertex_weighting provides a single vertex blend weight.
    ARB_vertex_blend generalizes this concept to a weight vector.  Both pieces
    of state are specified separately, and could be thought of as distinct.
    Should distinct bindings be provided in this extension?

      RESOLVED:  No.  No current implementation supports both extensions, but
      the vendors involved in this standardization process agree that the
      state should not be considered distinct.  If an implementation supported
      both extensions, the APIs would modify the same state.

    (86) Should this extension provide functionality for variable aliasing?
    If so, how should it be specified and what types of variables can be
    aliasesed?

      RESOLVED:  Yes, for all variable types.  The syntax is a simple text
      replacement:

        ALIAS a = b;

      This functionality allows applications to "share" variables, and thereby
      exceed implementation-dependent limits on the number of variable
      declarations.  This may be particularly significant for temporaries,
      where the limit on the number of variables may be fairly low.

    (87) How do you determine whether a given program option is supported by
    the GL implementation?

      RESOLVED:  Program options may be introduced in OpenGL extensions and
      may be added to future OpenGL specifications.  An option will be
      supported if and only if (1) the corresponding OpenGL extension appears
      in the implementation-dependent EXTENSIONS string or (2) the option is
      documented in the OpenGL specification version corresponding to the
      implementation's VERSION string.

      The ARB_position_invariant option is provided by this extension, and
      will always be available (provided this extension is supported).

    (88) What's the deal with binding the alpha component of light colors, fog
    colors, and material colors (other than diffuse)?  They don't do anything,
    right?

      RESOLVED:  The GL state for these different colors includes alpha
      components, which will be returned by queries.  However, in the
      conventional OpenGL pipeline, most of these alpha components are
      effectively ignored.  However, since they are present in the GL state,
      they will be exposed in bindings.  What is done with these alpha values
      in program mode is completely up to the vertex program.

      Vertex programs need to be careful to ensure that the alpha component is
      computed correctly when evaluating lighting equations.  When
      accumulating light contributions, it may be necessary to use write masks
      to disable writes to the alpha component.

    (89) The LOG instruction takes the logarithm of the absolute value of its
    operand while the LG2 instruction takes the logarithm of the operand
    itself.  In LG2, the logarithm of negative numbers is undefined.

      RESOLVED:  The LOG instruction is present for (1) compatibility with
      NV_vertex_program and DirectX 8 languages and (2) because it may
      outperform LG2 on some platforms.  For compatibility, it is defined to
      behave identically to existing languages.

    (90) With vertex programs, fog coordinates and point sizes can be computed
    on a per-vertex basis.  How are the fog coordinates and point sizes
    associated with vertices introduced by clipping computed?

      RESOLVED:  Fog coordinates and point sizes for clipped vertices are
      computed by interpolating the computed values at the original vertices
      in exactly the same manner as colors and texture coordinates are
      interpolated in section 2.13.8 of the OpenGL 1.3 specification.

    (91) Vertex programs support only RGBA colors, but do not support color
    index inputs or results.  What happens if an application uses vertex
    programs in color index mode.

      RESOLVED:  The results of vertex program execution are undefined if the
      GL is in color index mode.

    (92) Should automatic normalization of evaluated normals (AUTO_NORMAL) be
    supported when the GL is in vertex program mode?

      RESOLVED:  Automatic normalization of normals will be disabled in vertex
      program mode.  The current vertex program can easily normalize the
      normal if required.  This can lead to greater efficiency if the vertex
      program transforms the normal to another coordinate system such as
      eye-space with a transform that preserves vector length.  Then a single
      normalize after transform is more efficient than normalizing after
      evaluation and normalizing again after transform.  Conceptually, the
      normalize mandated for AUTO_NORMAL in section 5.1 is just one of the
      many transformation operations subsumed by vertex programs.

    (93) This extension allows applications to name their own variables.  What
    keywords should be reserved?

      RESOLVED:  Instruction names and declaration keywords (e.g., PARAM) will
      be reserved.  Additionally, since attribute, parameter, and result
      bindings are allowed in the program text, the binding prefix keywords
      "vertex", "state", "program", and "result" are reserved to simplify
      parsing.  This prevents the need to distinguish between
      "vertex.position" ("vertex" as a binding) and "vertex.xyzw" ("vertex" as
      a variable).

    (94) When counting the number of program parameter bindings, multiple
    constant vectors with the same components are counted only once.  How is
    this determined?

      RESOLVED:  The implementation does a numerical comparison after the
      specified constants are converted to an internal floating-point
      representation.  Due to floating-point representation limits, such
      conversions are not always precise.  Constants specified with different
      text that are "equivalent" (e.g., "12" and "1.2E+01") are not guaranteed
      to resolve to the same value.  Additionally, constants that are not
      "equivalent" but have only small relative differences (e.g., "200000000"
      and "200000001") may end up resolving to the same value.  Constants
      specified with the same text should always be identical.

    (95) What characters are allowed in identifier names?

      RESOLVED:  Letters ("A"-"Z", "a"-"z"), numbers ("0"-"9"), underscores
      ("_"), and dollar signs ("$").

    (96) How should future programmability extensions interact with this one?

      RESOLVED:  Future programmability extensions are expected to fall in one
      of two classes:  (1) extensions that bring programmability to new
      sections and (2) extensions the extend existing programmability models.
      The former class should introduce a new program target; the latter class
      would extend the functionality of an existing target.

      Recommendations for extensions introducing new program targets include:

        * Re-use and reference the functionality specified in this extension
          (or in a future OpenGL specification incorporating this extension)
          as much as possible, to maintain a consistent model.

        * Provide a program header allowing for easy identification and
          versioning of programs for the new target.

      Recommendations for extensions modifying existing program targets
      include:

        * The option mechanism (section 2.14.4.5) should be used to provide
          minor modifications to the program language.

        * The program header/version string (section 2.14.2) should be used to
          provide major modifications to the language, or potentially to
          provide a commonly used collection of options.  Program header
          string changes should be multi-vendor extensions as much as
          possible.

        * For portability, programs should not be allowed to use extended
          language features without specifying the corresponding program
          options or program header.


New Procedures and Functions

    void VertexAttrib1sARB(uint index, short x);
    void VertexAttrib1fARB(uint index, float x);
    void VertexAttrib1dARB(uint index, double x);
    void VertexAttrib2sARB(uint index, short x, short y);
    void VertexAttrib2fARB(uint index, float x, float y);
    void VertexAttrib2dARB(uint index, double x, double y);
    void VertexAttrib3sARB(uint index, short x, short y, short z);
    void VertexAttrib3fARB(uint index, float x, float y, float z);
    void VertexAttrib3dARB(uint index, double x, double y, double z);
    void VertexAttrib4sARB(uint index, short x, short y, short z, short w);
    void VertexAttrib4fARB(uint index, float x, float y, float z, float w);
    void VertexAttrib4dARB(uint index, double x, double y, double z, double w);
    void VertexAttrib4NubARB(uint index, ubyte x, ubyte y, ubyte z, ubyte w);

    void VertexAttrib1svARB(uint index, const short *v);
    void VertexAttrib1fvARB(uint index, const float *v);
    void VertexAttrib1dvARB(uint index, const double *v);
    void VertexAttrib2svARB(uint index, const short *v);
    void VertexAttrib2fvARB(uint index, const float *v);
    void VertexAttrib2dvARB(uint index, const double *v);
    void VertexAttrib3svARB(uint index, const short *v);
    void VertexAttrib3fvARB(uint index, const float *v);
    void VertexAttrib3dvARB(uint index, const double *v);
    void VertexAttrib4bvARB(uint index, const byte *v);
    void VertexAttrib4svARB(uint index, const short *v);
    void VertexAttrib4ivARB(uint index, const int *v);
    void VertexAttrib4ubvARB(uint index, const ubyte *v);
    void VertexAttrib4usvARB(uint index, const ushort *v);
    void VertexAttrib4uivARB(uint index, const uint *v);
    void VertexAttrib4fvARB(uint index, const float *v);
    void VertexAttrib4dvARB(uint index, const double *v);
    void VertexAttrib4NbvARB(uint index, const byte *v);
    void VertexAttrib4NsvARB(uint index, const short *v);
    void VertexAttrib4NivARB(uint index, const int *v);
    void VertexAttrib4NubvARB(uint index, const ubyte *v);
    void VertexAttrib4NusvARB(uint index, const ushort *v);
    void VertexAttrib4NuivARB(uint index, const uint *v);

    void VertexAttribPointerARB(uint index, int size, enum type, 
                                boolean normalized, sizei stride,
                                const void *pointer);

    void EnableVertexAttribArrayARB(uint index);
    void DisableVertexAttribArrayARB(uint index);

    void ProgramStringARB(enum target, enum format, sizei len, 
                          const void *string); 

    void BindProgramARB(enum target, uint program);

    void DeleteProgramsARB(sizei n, const uint *programs);

    void GenProgramsARB(sizei n, uint *programs);

    void ProgramEnvParameter4dARB(enum target, uint index,
                                  double x, double y, double z, double w);
    void ProgramEnvParameter4dvARB(enum target, uint index,
                                   const double *params);
    void ProgramEnvParameter4fARB(enum target, uint index,
                                  float x, float y, float z, float w);
    void ProgramEnvParameter4fvARB(enum target, uint index,
                                   const float *params);

    void ProgramLocalParameter4dARB(enum target, uint index,
                                    double x, double y, double z, double w);
    void ProgramLocalParameter4dvARB(enum target, uint index,
                                     const double *params);
    void ProgramLocalParameter4fARB(enum target, uint index,
                                    float x, float y, float z, float w);
    void ProgramLocalParameter4fvARB(enum target, uint index,
                                     const float *params);

    void GetProgramEnvParameterdvARB(enum target, uint index,
                                     double *params);
    void GetProgramEnvParameterfvARB(enum target, uint index, 
                                     float *params);

    void GetProgramLocalParameterdvARB(enum target, uint index,
                                       double *params);
    void GetProgramLocalParameterfvARB(enum target, uint index, 
                                       float *params);

    void GetProgramivARB(enum target, enum pname, int *params);

    void GetProgramStringARB(enum target, enum pname, void *string);

    void GetVertexAttribdvARB(uint index, enum pname, double *params);
    void GetVertexAttribfvARB(uint index, enum pname, float *params);
    void GetVertexAttribivARB(uint index, enum pname, int *params);

    void GetVertexAttribPointervARB(uint index, enum pname, void **pointer);

    boolean IsProgramARB(uint program);


New Tokens

    Accepted by the <cap> parameter of Disable, Enable, and IsEnabled, by the
    <pname> parameter of GetBooleanv, GetIntegerv, GetFloatv, and GetDoublev,
    and by the <target> parameter of ProgramStringARB, BindProgramARB,
    ProgramEnvParameter4[df][v]ARB, ProgramLocalParameter4[df][v]ARB,
    GetProgramEnvParameter[df]vARB, GetProgramLocalParameter[df]vARB,
    GetProgramivARB, and GetProgramStringARB.

        VERTEX_PROGRAM_ARB                              0x8620

    Accepted by the <cap> parameter of Disable, Enable, and IsEnabled, and by
    the <pname> parameter of GetBooleanv, GetIntegerv, GetFloatv, and
    GetDoublev:

        VERTEX_PROGRAM_POINT_SIZE_ARB                   0x8642
        VERTEX_PROGRAM_TWO_SIDE_ARB                     0x8643
        COLOR_SUM_ARB                                   0x8458

    Accepted by the <format> parameter of ProgramStringARB:

        PROGRAM_FORMAT_ASCII_ARB                        0x8875

    Accepted by the <pname> parameter of GetVertexAttrib[dfi]vARB:

        VERTEX_ATTRIB_ARRAY_ENABLED_ARB                 0x8622
        VERTEX_ATTRIB_ARRAY_SIZE_ARB                    0x8623
        VERTEX_ATTRIB_ARRAY_STRIDE_ARB                  0x8624
        VERTEX_ATTRIB_ARRAY_TYPE_ARB                    0x8625
        VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB              0x886A
        CURRENT_VERTEX_ATTRIB_ARB                       0x8626

    Accepted by the <pname> parameter of GetVertexAttribPointervARB:

        VERTEX_ATTRIB_ARRAY_POINTER_ARB                 0x8645

    Accepted by the <pname> parameter of GetProgramivARB:

        PROGRAM_LENGTH_ARB                              0x8627
        PROGRAM_FORMAT_ARB                              0x8876
        PROGRAM_BINDING_ARB                             0x8677
        PROGRAM_INSTRUCTIONS_ARB                        0x88A0
        MAX_PROGRAM_INSTRUCTIONS_ARB                    0x88A1
        PROGRAM_NATIVE_INSTRUCTIONS_ARB                 0x88A2
        MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB             0x88A3
        PROGRAM_TEMPORARIES_ARB                         0x88A4
        MAX_PROGRAM_TEMPORARIES_ARB                     0x88A5
        PROGRAM_NATIVE_TEMPORARIES_ARB                  0x88A6
        MAX_PROGRAM_NATIVE_TEMPORARIES_ARB              0x88A7
        PROGRAM_PARAMETERS_ARB                          0x88A8
        MAX_PROGRAM_PARAMETERS_ARB                      0x88A9
        PROGRAM_NATIVE_PARAMETERS_ARB                   0x88AA
        MAX_PROGRAM_NATIVE_PARAMETERS_ARB               0x88AB
        PROGRAM_ATTRIBS_ARB                             0x88AC
        MAX_PROGRAM_ATTRIBS_ARB                         0x88AD
        PROGRAM_NATIVE_ATTRIBS_ARB                      0x88AE
        MAX_PROGRAM_NATIVE_ATTRIBS_ARB                  0x88AF
        PROGRAM_ADDRESS_REGISTERS_ARB                   0x88B0
        MAX_PROGRAM_ADDRESS_REGISTERS_ARB               0x88B1
        PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB            0x88B2
        MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB        0x88B3
        MAX_PROGRAM_LOCAL_PARAMETERS_ARB                0x88B4
        MAX_PROGRAM_ENV_PARAMETERS_ARB                  0x88B5
        PROGRAM_UNDER_NATIVE_LIMITS_ARB                 0x88B6

    Accepted by the <pname> parameter of GetProgramStringARB:

        PROGRAM_STRING_ARB                              0x8628

    Accepted by the <pname> parameter of GetBooleanv, GetIntegerv,
    GetFloatv, and GetDoublev:

        PROGRAM_ERROR_POSITION_ARB                      0x864B
        CURRENT_MATRIX_ARB                              0x8641
        TRANSPOSE_CURRENT_MATRIX_ARB                    0x88B7
        CURRENT_MATRIX_STACK_DEPTH_ARB                  0x8640
        MAX_VERTEX_ATTRIBS_ARB                          0x8869
        MAX_PROGRAM_MATRICES_ARB                        0x862F
        MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB              0x862E

    Accepted by the <name> parameter of GetString:

        PROGRAM_ERROR_STRING_ARB                        0x8874

    Accepted by the <mode> parameter of MatrixMode:
    
        MATRIX0_ARB                                     0x88C0
        MATRIX1_ARB                                     0x88C1
        MATRIX2_ARB                                     0x88C2
        MATRIX3_ARB                                     0x88C3
        MATRIX4_ARB                                     0x88C4
        MATRIX5_ARB                                     0x88C5
        MATRIX6_ARB                                     0x88C6
        MATRIX7_ARB                                     0x88C7
        MATRIX8_ARB                                     0x88C8
        MATRIX9_ARB                                     0x88C9
        MATRIX10_ARB                                    0x88CA
        MATRIX11_ARB                                    0x88CB
        MATRIX12_ARB                                    0x88CC
        MATRIX13_ARB                                    0x88CD
        MATRIX14_ARB                                    0x88CE
        MATRIX15_ARB                                    0x88CF
        MATRIX16_ARB                                    0x88D0
        MATRIX17_ARB                                    0x88D1
        MATRIX18_ARB                                    0x88D2
        MATRIX19_ARB                                    0x88D3
        MATRIX20_ARB                                    0x88D4
        MATRIX21_ARB                                    0x88D5
        MATRIX22_ARB                                    0x88D6
        MATRIX23_ARB                                    0x88D7
        MATRIX24_ARB                                    0x88D8
        MATRIX25_ARB                                    0x88D9
        MATRIX26_ARB                                    0x88DA
        MATRIX27_ARB                                    0x88DB
        MATRIX28_ARB                                    0x88DC
        MATRIX29_ARB                                    0x88DD
        MATRIX30_ARB                                    0x88DE
        MATRIX31_ARB                                    0x88DF

Additions to Chapter 2 of the OpenGL 1.3 Specification (OpenGL Operation)

    Modify Section 2.6, Begin/End Paradigm (p. 12)

    (modify last paragraph, p. 12) ... In addition, a current normal, a
    current color, multiple current texture coordinate sets, and multiple
    generic vertex attributes may be used in processing each vertex.  Normals
    are used by the GL in lighting calculations; the current normal is a
    three-dimensional vector that may be set by sending three coordinates that
    specify it.  Texture coordinates determine how a texture image is mapped
    onto a primitive.  Multiple sets of texture coordinates may be used to
    specify how multiple texture images are mapped onto a primitive.  Generic
    vertex attributes do not have any specific function but can be used in
    vertex program mode (section 2.14) to compute final values for any data
    associated with a vertex.


    Modify Section 2.6.3, GL Commands within Begin/End (p. 19)

    (modify first paragraph of section, p. 19) The only GL commands that are
    allowed within any Begin/End pairs are the commands for specifying vertex
    coordinates, vertex color, normal coordinates, texture coordinates, and
    generic vertex attributes (Vertex, Color, Index, Normal, TexCoord,
    VertexAttrib*ARB), ...


    Modify Section 2.7, Vertex Specification (p. 19)

    (remove the "Finally" from the next-to-last paragraph, p. 20) There are
    several ways to set the current color. The GL stores both a current
    single-valued color index, and a current four-valued RGBA color. One

    (add new paragraph before last paragraph of section, p. 21) Vertex
    programs (section 2.14) can access an array of four-component generic
    current vertex attributes.  The first entry of this array is numbered
    zero, and the number of entries in the array is given by the
    implementation-dependent constant MAX_VERTEX_ATTRIBS_ARB.  The commands

      void VertexAttrib{1234}{sfd}ARB(uint index, T coords);
      void VertexAttrib{123}{sfd}vARB(uint index, T coords);
      void VertexAttrib4{bsifd ubusui}vARB(uint index, T coords);

    specify the current vertex attribute numbered <index>, whose components
    are named <x>, <y>, <z>, and <w>.  The VertexAttrib1ARB family of commands
    sets the <x> coordinate to the provided single argument while setting <y>
    and <z> to 0 and <w> to 1.  Similarly, VertexAttrib2ARB commands set <x>
    and <y> to the specified values, <z> to 0 and <w> to 1; VertexAttrib3ARB
    commands set <x>, <y>, and <z>, with <w> set to 1, and VertexAttrib4ARB
    commands set all four coordinates.  The error INVALID_VALUE is generated
    if <index> is greater than or equal to MAX_VERTEX_ATTRIBS_ARB.

    The commands

      void VertexAttrib4NubARB(uint index, T coords);
      void VertexAttrib4N{bsi ubusui}vARB(uint index, T coords);

    also specify vertex attributes with fixed-point coordinates that are
    scaled to the range [0,1] or [-1,1], according to Table 2.6.

    Setting generic vertex attribute zero specifies a vertex; the four vertex
    coordinates are taken from the values of attribute zero.  A Vertex2,
    Vertex3, or Vertex4 command is completely equivalent to the corresponding
    VertexAttrib command with an index of zero.  Setting any other generic
    vertex attribute updates the current values of the attribute.  There are
    no current values for vertex attribute zero.

    Implementations may, but do not necessarily, use the same storage for the
    current values of generic and certain conventional vertex attributes.
    When any generic vertex attribute other than zero is specified, the
    current values for the corresponding conventional attribute in Table X.1
    become undefined.  Additionally, when a conventional vertex attribute is
    specified, the current values for the corresponding generic vertex
    attribute in Table X.1 become undefined.  For example, setting the current
    normal will leave generic vertex attribute 2 undefined, and vice versa.

    Generic
    Attribute   Conventional Attribute       Conventional Attribute Command
    ---------   ------------------------     ------------------------------
         0      vertex position              Vertex
         1      vertex weights 0-3           WeightARB, VertexWeightEXT
         2      normal                       Normal
         3      primary color                Color
         4      secondary color              SecondaryColorEXT
         5      fog coordinate               FogCoordEXT
         6      -                            -
         7      -                            -
         8      texture coordinate set 0     MultiTexCoord(TEXTURE0, ...)
         9      texture coordinate set 1     MultiTexCoord(TEXTURE1, ...)
        10      texture coordinate set 2     MultiTexCoord(TEXTURE2, ...)
        11      texture coordinate set 3     MultiTexCoord(TEXTURE3, ...)
        12      texture coordinate set 4     MultiTexCoord(TEXTURE4, ...)
        13      texture coordinate set 5     MultiTexCoord(TEXTURE5, ...)
        14      texture coordinate set 6     MultiTexCoord(TEXTURE6, ...)
        15      texture coordinate set 7     MultiTexCoord(TEXTURE7, ...)
       8+n      texture coordinate set n     MultiTexCoord(TEXTURE0+n, ...)

    Table X.1, Generic and Conventional Vertex Attribute Mappings.  For each
    row, the current value of the conventional attribute becomes undefined
    when the corresponding generic attribute is set, and vice versa.
    Attribute zero corresponds to the vertex position and has no current
    state.

    Setting any conventional vertex attribute not listed in Table X.1
    (including vertex weights 4 and above, if supported) will not cause any
    generic vertex attribute to become undefined, and such attributes will not
    become undefined when any generic vertex attribute is set.



    (modify the last paragraph in the section, p.21) The state required to
    support vertex specification consists of four floating-point numbers per
    texture unit to store the current texture coordinates s, t, r, and q,
    three floating-point numbers to store the three coordinates of the current
    normal, four floating-point values to store the current RGBA color, one
    floating-point value to store the current color index, and
    MAX_VERTEX_ATTRIBS_ARB-1 four-component floating-point vectors for generic
    vertex attributes.  There is no notion of a current vertex, so no state is
    devoted to vertex coordinates or vertex attribute zero.  The initial
    texture coordinates are (S,T,R,Q) = (0,0,0,1) for each texture unit. The
    initial current normal has coordinates (0,0,1). The initial RGBA color is
    (R,G,B,A) = (1,1,1,1). The initial color index is 1.  The initial values
    for all generic vertex attributes are undefined.

    
    Modify Section 2.8, Vertex Arrays (p. 21)

    (modify first paragraph of section, p.21) The vertex specification
    commands described in section 2.7 accept data in almost any format, but
    their use requires many command executions to specify even simple
    geometry. Vertex data may also be placed into arrays that are stored in
    the client's address space. Blocks of data in these arrays may then be
    used to specify multiple geometric primitives through the execution of a
    single GL command. The client may specify up to 5 plus the values of
    MAX_TEXTURE_UNITS and MAX_VERTEX_ATTRIBS_ARB arrays: one each to store
    vertex coordinates, edge flags, colors, color indices, normals, one or
    more texture coordinate sets, and one or more generic vertex attributes.
    The commands

      ...

      void VertexAttribPointerARB(uint index, int size, enum type, 
                                  boolean normalized, sizei stride, 
                                  const void *pointer);

    describe the locations and organizations...

    (add after the first paragraph, p.22) The <index> parameter in the
    VertexAttribPointer command identifies the generic vertex attribute array
    being described.  The error INVALID_VALUE is generated if <index> is
    greater than or equal to MAX_VERTEX_ATTRIBS_ARB.  The <normalized>
    parameter in the VertexAttribPointer command identifies whether
    fixed-point types should be normalized when converted to floating-point.
    If <normalized> is TRUE, fixed-point data are converted as specified in
    Table 2.6; otherwise, the fixed-point values are converted directly.

    (add after first paragraph, p.23) An individual generic vertex attribute
    array is enabled or disabled by calling one of

      void EnableVertexAttribArrayARB(uint index);
      void DisableVertexAttribArrayARB(uint index);

    where <index> identifies the generic vertex attribute array to enable or
    disable.  The error INVALID_VALUE is generated if <index> is greater than
    or equal to MAX_VERTEX_ATTRIBS_ARB.

    (modify Table 2.4, p.23)

                                       Normal    
      Command                 Sizes    ized?   Types
      ----------------------  -------  ------  --------------------------------
      VertexPointer           2,3,4     no     short, int, float, double
      NormalPointer           3         yes    byte, short, int, float, double
      ColorPointer            3,4       yes    byte, ubyte, short, ushort,
                                               int, uint, float, double
      IndexPointer            1         no     ubyte, short, int, float, double
      TexCoordPointer         1,2,3,4   no     short, int, float, double
      EdgeFlagPointer         1         no     boolean
      VertexAttribPointerARB  1,2,3,4   flag   byte, ubyte, short, ushort,
                                               int, uint, float, double
      WeightPointerARB        >=1       yes    byte, ubyte, short, ushort,
                                               int, uint, float, double
      VertexWeightPointerEXT  1         n/a    float
      SecondaryColor-         3         yes    byte, ubyte, short, ushort,
        PointerEXT                             int, uint, float, double
      FogCoordPointerEXT      1         n/a    float, double
      MatrixIndexPointerARB   >=1       no     ubyte, ushort, uint

      Table 2.4: Vertex array sizes (values per vertex) and data types.  The
      "normalized" column indicates whether fixed-point types are accepted
      directly or normalized to [0,1] (for unsigned types) or [-1,1] (for
      singed types). For generic vertex attributes, fixed-point data are
      normalized if and only if the <normalized> flag is set.

    (modify last paragraph, p.23) The command

      void ArrayElement(int i); 

    transfers the ith element of every enabled array to the GL.  The effect of
    ArrayElement(i) is the same as the effect of the command sequence

      if (ARB_vertex_blend vertex weight array enabled) {
        Weight[type]vARB(vertex weight array size, 
                         vertex weight array element i);
      }
      if (EXT_vertex_weighting vertex weight array enabled) {
        VertexWeight[type]vARB(vertex weight array element i);
      }
      if (normal array enabled) {
        Normal3[type]v(normal array element i);
      }
      if (color array enabled) {
        Color[size][type]v(color array element i);
      }
      if (secondary color array enabled) {
        SecondaryColor3[type]vEXT(secondary color array element i);
      }
      if (fog coordinate array enabled) {
        FogCoord[type]vEXT(fog coordinate array element i);
      }
      if (matrix index array enabled) {
        MatrixIndex[type]vARB(matrix index array size,
                              matrix index array element i);
      }
      for (j = 0; j < textureUnits; j++) {
        if (texture coordinate set j array enabled) {
          MultiTexCoord[size][type]v(TEXTURE0 + j,
                                     texture coordinate set j
                                     array element i);
      }
      if (color index array enabled) {
        Index[type]v(color index array element i);
      }
      if (edge flag array enabled) {
        EdgeFlagv(edge flag array element i);
      }
      for (j = 1; j < genericAttributes; j++) {
        if (generic vertex attribute j array enabled) {
          if (generic vertex attribute j array normalization flag
              is set, and type is not FLOAT or DOUBLE) {
            VertexAttrib[size]N[type]vARB(j, generic vertex attribute j
                                             array element i);
          } else {
            VertexAttrib[size][type]vARB(j, generic vertex attribute j
                                            array element i);
          }
        }
      }
      if (generic attribute array 0 enabled) {
        if (generic vertex attribute j array normalization flag
            is set, and type is not FLOAT or DOUBLE) {
          VertexAttrib[size]N[type]vARB(0, generic vertex attribute 0
                                           array element i);
        } else {
          VertexAttrib[size][type]vARB(0, generic vertex attribute 0
                                          array element i);
        }
      } else if (vertex array enabled) {
        Vertex[size][type]vARB(vertex array element i);
      }

    where <textureUnits> and <genericAttributes> give the number of texture
    units and generic vertex attributes supported by the implementation,
    respectively.  "[size]" and "[type]" correspond to the size and type of
    the corresponding array.  For generic vertex attributes, it is assumed
    that a complete set of vertex attribute commands exists, even though not
    all such functions are provided by the GL.  Both generic attribute array
    zero and the vertex array can specify a vertex if enabled, but only one
    such array is used.  As described in section 2.7, setting a generic vertex
    attributes listed in Table X.1 will leave the corresponding conventional
    vertex attribute undefined, and vice versa.


    (modify last paragraph of section, p.28) If the number of supported
    texture units (the value of MAX TEXTURE UNITS) is m and the number of
    supported generic vertex attributes (MAX_VERTEX_ATTRIBS_ARB) is n, then
    the client state required to implement vertex arrays consists of 5+m+n
    boolean enables, 5+m+n memory pointers, 5+m+n integer stride values, 4+m+n
    symbolic constants representing array types, 2+m+n integers representing
    values per element, and n boolean normalization flags. In the initial
    state, the enable values are each disabled, the memory pointers are each
    null, the strides are each zero, the array types are each FLOAT, the
    integers representing values per element are each four, and the
    normalization flags are disabled..


    Modify Section 2.10, Coordinate Transformations (p. 29)

    (add new paragraphs) Vertex attributes are transformed before the vertex
    is used to generate primitives for rasterization, establish a raster
    position, or generate vertices for selection or feedback.  The attributes
    of each vertex are transformed using one of two vertex transformation
    modes.  The first mode, described in this and subsequent sections, is GL's
    conventional vertex transformation model.  The second mode, known as
    vertex program mode and described in section 2.14, transforms vertex
    attributes as specified in an application-supplied vertex program.

    Vertex program mode is enabled and disabled, respectively, by

      void Enable(enum target);

    and

      void Disable(enum target);

    with <target> equal to VERTEX_PROGRAM_ARB.  When vertex program mode is
    enabled, vertices are transformed by the currently bound vertex program as
    discussed in section 2.14.

    When vertex program mode is disabled, vertices, normals, and texture
    coordinates are transformed before their coordinates are used to produce
    an image in the framebuffer.  We begin with a description of how vertex
    coordinates are transformed and how the transformation is controlled in
    this case.  The discussion that continues through section 2.13 applies
    when vertex program mode is disabled.


    Modify Section 2.10.2, Matrices (p. 31)

    (modify 1st paragraph) The projection matrix and model-view matrix are set
    and modified with a variety of commands.  The affected matrix is
    determined by the current matrix mode.  The current matrix mode is set
    with

      void MatrixMode(enum mode);

    which takes one of the pre-defined constants TEXTURE, MODELVIEW, COLOR,
    PROJECTION, or MATRIX<i>_ARB as the argument.  In the case of
    MATRIX<i>_ARB, <i> is an integer between 0 and <n>-1 indicating one of <n>
    program matrices where <n> is the value of the implementation defined
    constant MAX_PROGRAM_MATRICES_ARB.  Such program matrices are described in
    section 2.14.6.  TEXTURE is described later in section 2.10.2, and COLOR
    is described in section 3.6.3.  If the current matrix mode is MODELVIEW,
    then matrix operations apply to the model-view matrix; if PROJECTION, then
    they apply to the projection matrix.

    (modify last paragraph of section) The state required to implement
    transformations consists of a <n>-value integer indicating the current
    matrix mode (where <n> is 4 + the number of supported texture and program
    matrices), a stack of at least two 4x4 matrices for each of COLOR,
    PROJECTION, and TEXTURE with associated stack pointers, <n> stacks (where
    <n> is at least 8) of at least one 4x4 matrix for each MATRIX<i>_ARB with
    associated stack pointers, and a stack of at least 32 4x4 matrices with an
    associated stack pointer for MODELVIEW.  Initially, there is only one
    matrix on each stack, and all matrices are set to the identity.  The
    initial matrix mode is MODELVIEW.  The initial value of ACTIVE_TEXTURE is
    TEXTURE0.


    Modify Section 2.11, Clipping (p. 39)

    (add to end of next-to-last paragraph, p. 40) ... User clipping is not
    supported in vertex program mode if the current program is not
    position-invariant (section 2.14.4.5.1).  In this case, client-defined
    clip planes are always treated as disabled.


    Modify Section 2.12, Current Raster Position (p. 42)

    (modify fourth paragraph, p.42) The coordinates are treated as if they
    were specified in a Vertex command.  If vertex program mode is enabled,
    the currently bound vertex program is executed, using the x, y, z, and w
    coordinates as the object coordinates of the vertex.  Otherwise, the x, y,
    z, and w coordinates are transformed by the current model-view and
    projection matrices. These coordinates, along with current values, are
    used to generate a color and texture coordinates just as is done for a
    vertex. The color and texture coordinates produced using either method
    replace the color and texture coordinates stored in the current raster
    position's associated data.  When in vertex program mode, the "x"
    component of the fog coordinate result replaces the current raster
    distance; otherwise, the distance from the origin of the eye coordinate
    system to the vertex as transformed by only the current model-view matrix
    replaces the current raster distance.  The latter distance can be
    approximated (see section 3.10).

    Rename and Modify Section 2.13.8, Color and Vertex Data Clipping (p.56)

    (modify second paragraph, p.57) Texture coordinates, as well as fog
    coordinates and point sizes computed on a per-vertex basis, must also be
    clipped when a primitive is clipped.  The method is exactly analogous to
    that used for color clipping.


    Add New Section 2.14 and subsections (p. 57).

    Section 2.14, Vertex Programs
    
    The conventional GL vertex transformation model described in sections 2.10
    through 2.13 is a configurable but essentially hard-wired sequence of
    per-vertex computations based on a canonical set of per-vertex parameters
    and vertex transformation related state such as transformation matrices,
    lighting parameters, and texture coordinate generation parameters.  The
    general success and utility of the conventional GL vertex transformation
    model reflects its basic correspondence to the typical vertex
    transformation requirements of 3D applications.

    However when the conventional GL vertex transformation model is not
    sufficient, the vertex program mode provides a substantially more flexible
    model for vertex transformation.  The vertex program mode permits
    applications to define their own vertex programs.

    A vertex program is a character string that specifies a sequence of
    operations to perform.  Vertex program instructions are typically
    4-component vector operations that operate on per-vertex attributes and
    program parameters.  Vertex programs execute on a per-vertex basis and
    operate on each vertex completely independently from any other vertices.
    Vertex programs execute a finite fixed sequence of instructions with no
    branching or looping.  Vertex programs execute without data hazards so
    results computed in one instruction can be used immediately afterwards.
    The result of a vertex program is a set of vertex result registers that
    becomes the set of transformed vertex attributes used during clipping and
    primitive assembly.

    Vertex programs are defined to operate only in RGBA mode.  The results of
    vertex program execution are undefined if the GL is in color index mode.


    Section 2.14.1,  Program Objects

    The GL provides one or more program targets, each identifying a portion of
    the GL that can be controlled through application-specified programs.  The
    program target for vertex programs is VERTEX_PROGRAM_ARB.  Each program
    target has an associated program object, called the current program
    object.  Each program target also has a default program object, which is
    initially the current program object.

    Each program object has an associated program string.  The command

      ProgramStringARB(enum target, enum format, sizei len, 
                       const void *string);

    updates the program string for the current program object for <target>.
    <format> describes the format of the program string, which must currently
    be PROGRAM_FORMAT_ASCII_ARB.  <string> is a pointer to the array of bytes
    representing the program string being loaded, which need not be
    null-terminated.  The length of the array is given by <len>.  If <string>
    is null-terminated, <len> should not include the terminator.

    When a program string is loaded, it is interpreted according to syntactic
    and semantic rules corresponding to the program target specified by
    <target>.  If a program violates the syntactic or semantic restrictions of
    the program target, ProgramStringARB generates the error
    INVALID_OPERATION.

    Additionally, ProgramString will update the program error position
    (PROGRAM_ERROR_POSITION_ARB) and error string (PROGRAM_ERROR_STRING_ARB).
    If a program fails to load, the value of the program error position is set
    to the ubyte offset into the specified program string indicating where the
    first program error was detected.  If the program fails to load because of
    a semantic restriction that is not detected until the program is fully
    scanned, the error position is set to the value of <len>.  If a program
    loads successfully, the error position is set to the value negative one.
    The implementation-dependent program error string contains one or more
    error or warning messages.  If a program loads succesfully, the error
    string may either contain warning messages or be empty.

    Each program object has an associated array of program local parameters.
    The number and type of program local parameters is target- and
    implementation-dependent.  For vertex programs, program local parameters
    are four-component floating-point vectors.  The number of vectors is given
    by the implementation-dependent constant MAX_PROGRAM_LOCAL_PARAMETERS_ARB,
    which must be at least 96.  The commands

      void ProgramLocalParameter4fARB(enum target, uint index,
                                      float x, float y, float z, float w);
      void ProgramLocalParameter4fvARB(enum target, uint index, 
                                       const float *params);
      void ProgramLocalParameter4dARB(enum target, uint index,
                                      double x, double y, double z, double w);
      void ProgramLocalParameter4dvARB(enum target, uint index, 
                                       const double *params);

    update the values of the program local parameter numbered <index>
    belonging to the program object currently bound to <target>.  For
    ProgramLocalParameter4fARB and ProgramLocalParameter4dARB, the four
    components of the parameter are updated with the values of <x>, <y>, <z>,
    and <w>, respectively.  For ProgramLocalParameter4fvARB and
    ProgramLocalParameter4dvARB, the four components of the parameter are
    updated with the array of four values pointed to by <params>.  The error
    INVALID_VALUE is generated if <index> is greater than or equal to the
    number of program local parameters supported by <target>.

    Additionally, each program target has an associated array of program
    environment parameters.  Unlike program local parameters, program
    environment parameters are shared by all program objects of a given
    target.  The number and type of program environment parameters is target-
    and implementation-dependent.  For vertex programs, program environment
    parameters are four-component floating-point vectors.  The number of
    vectors is given by the implementation-dependent constant
    MAX_PROGRAM_ENV_PARAMETERS_ARB, which must be at least 96.  The commands

      void ProgramEnvParameter4fARB(enum target, uint index,
                                    float x, float y, float z, float w);
      void ProgramEnvParameter4fvARB(enum target, uint index,
                                     const float *params);
      void ProgramEnvParameter4dARB(enum target, uint index,
                                    double x, double y, double z, double w);
      void ProgramEnvParameter4dvARB(enum target, uint index,
                                     const double *params);

    update the values of the program environment parameter numbered <index>
    for the given program target <target>.  For ProgramEnvParameter4fARB and
    ProgramEnvParameter4dARB, the four components of the parameter are updated
    with the values of <x>, <y>, <z>, and <w>, respectively.  For
    ProgramEnvParameter4fvARB and ProgramEnvParameter4dvARB, the four
    components of the parameter are updated with the array of four values
    pointed to by <params>.  The error INVALID_VALUE is generated if <index>
    is greater than or equal to the number of program environment parameters
    supported by <target>.

    Each program target has a default program object.  Additionally, named
    program objects can be created and operated upon.  The name space for
    program objects is the positive integers and is shared by programs of all
    targets.  The name zero is reserved by the GL.

    A named program object is created by binding an unused program object name
    to a valid program target.  The binding is effected by calling

      BindProgramARB(enum target, uint program);

    with <target> set to the desired program target and <program> set to the
    unused program name.  The resulting program object has a program target
    given by <target> and is assigned target-specific default values (see
    section 2.14.7 for vertex programs).  BindProgramARB may also be used to
    bind an existing program object to a program target.  If <program> is
    zero, the default program object for <target> is bound.  If <program> is
    the name of an existing program object whose associated program target is
    <target>, the named program object is bound.  The error INVALID_OPERATION
    is generated if <program> names an existing program object whose
    associated program target is anything other than <target>.

    Programs objects are deleted by calling

      void DeleteProgramsARB(sizei n, const uint *programs);

    <programs> contains <n> names of programs to be deleted.  After a program
    object is deleted, its name is again unused.  If a program object that is
    bound to any target is deleted, it is as though BindProgramARB is first
    executed with same target and a <program> of zero.  Unused names in
    <programs> are silently ignored, as is the value zero.

    The command

      void GenProgramsARB(sizei n, uint *programs);

    returns <n> currently unused program names in <programs>.  These names are
    marked as used, for the purposes of GenProgramsARB only, but objects are
    created only when they are first bound using BindProgramARB.


    Section 2.14.2,  Vertex Program Grammar and Semantic Restrictions

    Vertex program strings are specified as an array of ASCII characters
    containing the program text.  When a vertex program is loaded by a call to
    ProgramStringARB, the program string is parsed into a set of tokens
    possibly separated by whitespace.  Spaces, tabs, newlines, carriage
    returns, and comments are considered whitespace.  Comments begin with the
    character "#" and are terminated by a newline, a carriage return, or the
    end of the program array.

    The Backus-Naur Form (BNF) grammar below specifies the syntactically valid
    sequences for vertex programs.  The set of valid tokens can be inferred
    from the grammar.  The token "" represents an empty string and is used to
    indicate optional rules.  A program is invalid if it contains any
    undefined tokens or characters.

    A vertex program is required to begin with the header string "!!ARBvp1.0",
    without any preceding whitespace.  This string identifies the subsequent
    program text as a vertex program (version 1.0) that should be parsed
    according to the following grammar and semantic rules.  Program string
    parsing begins with the character immediately following the header string.

    <program>              ::= <optionSequence> <statementSequence> "END"

    <optionSequence>       ::= <optionSequence> <option>
                             | ""

    <option>               ::= "OPTION" <identifier> ";"

    <statementSequence>    ::= <statementSequence> <statement>
                             | ""

    <statement>            ::= <instruction> ";"
                             | <namingStatement> ";"

    <instruction>          ::= <ARL_instruction>
                             | <VECTORop_instruction>
                             | <SCALARop_instruction>
                             | <BINSCop_instruction>
                             | <BINop_instruction>
                             | <TRIop_instruction>
                             | <SWZ_instruction>

    <ARL_instruction>      ::= "ARL" <maskedAddrReg> "," <scalarSrcReg>

    <VECTORop_instruction> ::= <VECTORop> <maskedDstReg> "," <swizzleSrcReg>

    <VECTORop>             ::= "ABS"
                             | "FLR"
                             | "FRC"
                             | "LIT"
                             | "MOV"

    <SCALARop_instruction> ::= <SCALARop> <maskedDstReg> "," <scalarSrcReg>

    <SCALARop>             ::= "EX2"
                             | "EXP"
                             | "LG2"
                             | "LOG"                          
                             | "RCP"
                             | "RSQ"

    <BINSCop_instruction>  ::= <BINSCop> <maskedDstReg> "," <scalarSrcReg> ","
                               <scalarSrcReg> 

    <BINSCop>              ::= "POW"
 
    <BINop_instruction>    ::= <BINop> <maskedDstReg> ","
                               <swizzleSrcReg> "," <swizzleSrcReg>

    <BINop>                ::= "ADD"
                             | "DP3"
                             | "DP4"
                             | "DPH"
                             | "DST"
                             | "MAX"
                             | "MIN"
                             | "MUL"
                             | "SGE"
                             | "SLT"
                             | "SUB"
                             | "XPD"

    <TRIop_instruction>    ::= <TRIop> <maskedDstReg> ","
                               <swizzleSrcReg> "," <swizzleSrcReg> ","
                               <swizzleSrcReg>

    <TRIop>                ::= "MAD"

    <SWZ_instruction>      ::= "SWZ" <maskedDstReg> "," <srcReg> "," 
                               <extendedSwizzle>

    <scalarSrcReg>         ::= <optionalSign> <srcReg> <scalarSuffix>

    <swizzleSrcReg>        ::= <optionalSign> <srcReg> <swizzleSuffix>

    <maskedDstReg>         ::= <dstReg> <optionalMask>

    <maskedAddrReg>        ::= <addrReg> <addrWriteMask>

    <extendedSwizzle>      ::= <extSwizComp> "," <extSwizComp> "," 
                                 <extSwizComp> "," <extSwizComp>

    <extSwizComp>          ::= <optionalSign> <extSwizSel>

    <extSwizSel>           ::= "0" 
                             | "1" 
                             | <component>

    <srcReg>               ::= <vertexAttribReg>
                             | <temporaryReg>
                             | <progParamReg>

    <dstReg>               ::= <temporaryReg>
                             | <vertexResultReg>

    <vertexAttribReg>      ::= <establishedName>
                             | <vtxAttribBinding>

    <temporaryReg>         ::= <establishedName>

    <progParamReg>         ::= <progParamSingle>
                             | <progParamArray> "[" <progParamArrayMem> "]"
                             | <paramSingleItemUse>

    <progParamSingle>      ::= <establishedName>

    <progParamArray>       ::= <establishedName>
    
    <progParamArrayMem>    ::= <progParamArrayAbs>
                             | <progParamArrayRel>
                             
    <progParamArrayAbs>    ::= <integer>

    <progParamArrayRel>    ::= <addrReg> <addrComponent> <addrRegRelOffset>

    <addrRegRelOffset>     ::= ""
                             | "+" <addrRegPosOffset>
                             | "-" <addrRegNegOffset>

    <addrRegPosOffset>     ::= <integer> from 0 to 63

    <addrRegNegOffset>     ::= <integer> from 0 to 64

    <vertexResultReg>      ::= <establishedName>
                             | <resultBinding>

    <addrReg>              ::= <establishedName>

    <addrComponent>        ::= "." "x"

    <addrWriteMask>        ::= "." "x"

    <scalarSuffix>         ::= "." <component>

    <swizzleSuffix>        ::= ""
                             | "." <component>
                             | "." <component> <component>
                                   <component> <component>

    <component>            ::= "x"
                             | "y"
                             | "z"
                             | "w"

    <optionalMask>         ::= ""
                             | "." "x"
                             | "." "y"
                             | "." "xy"
                             | "." "z"
                             | "." "xz"
                             | "." "yz"
                             | "." "xyz"
                             | "." "w"
                             | "." "xw"
                             | "." "yw"
                             | "." "xyw"
                             | "." "zw"
                             | "." "xzw"
                             | "." "yzw"
                             | "." "xyzw"

    <namingStatement>      ::= <ATTRIB_statement>
                             | <PARAM_statement>
                             | <TEMP_statement>
                             | <ADDRESS_statement>
                             | <OUTPUT_statement>
                             | <ALIAS_statement>

    <ATTRIB_statement>     ::= "ATTRIB" <establishName> "="
                                 <vtxAttribBinding>

    <vtxAttribBinding>     ::= "vertex" "." <vtxAttribItem>

    <vtxAttribItem>        ::= "position"
                             | "weight" <vtxOptWeightNum>
                             | "normal"
                             | "color" <optColorType>
                             | "fogcoord"
                             | "texcoord" <optTexCoordNum>
                             | "matrixindex" "[" <vtxWeightNum> "]"
                             | "attrib" "[" <vtxAttribNum> "]"

    <vtxAttribNum>         ::= <integer> from 0 to MAX_VERTEX_ATTRIBS_ARB-1

    <vtxOptWeightNum>      ::= ""
                             | "[" <vtxWeightNum> "]"

    <vtxWeightNum>         ::= <integer> from 0 to MAX_VERTEX_UNITS_ARB-1,
                                 must be divisible by four

    <PARAM_statement>      ::= <PARAM_singleStmt>
                             | <PARAM_multipleStmt>

    <PARAM_singleStmt>     ::= "PARAM" <establishName> <paramSingleInit>

    <PARAM_multipleStmt>   ::= "PARAM" <establishName> "[" <optArraySize> "]"
                                   <paramMultipleInit>

    <optArraySize>         ::= ""
                             | <integer> from 1 to MAX_PROGRAM_PARAMETERS_ARB
                                 (maximum number of allowed program 
                                  parameter bindings)

    <paramSingleInit>      ::= "=" <paramSingleItemDecl>

    <paramMultipleInit>    ::= "=" "{" <paramMultInitList> "}"

    <paramMultInitList>    ::= <paramMultipleItem>
                             | <paramMultipleItem> "," <paramMultiInitList>

    <paramSingleItemDecl>  ::= <stateSingleItem>
                             | <programSingleItem>
                             | <paramConstDecl>

    <paramSingleItemUse>   ::= <stateSingleItem>
                             | <programSingleItem>
                             | <paramConstUse>

    <paramMultipleItem>    ::= <stateMultipleItem>
                             | <programMultipleItem>
                             | <paramConstDecl>

    <stateMultipleItem>    ::= <stateSingleItem>
                             | "state" "." <stateMatrixRows>

    <stateSingleItem>      ::= "state" "." <stateMaterialItem>
                             | "state" "." <stateLightItem>
                             | "state" "." <stateLightModelItem>
                             | "state" "." <stateLightProdItem>
                             | "state" "." <stateTexGenItem>
                             | "state" "." <stateFogItem>
                             | "state" "." <stateClipPlaneItem>
                             | "state" "." <statePointItem>
                             | "state" "." <stateMatrixRow>

    <stateMaterialItem>    ::= "material" <optFaceType> "." <stateMatProperty>

    <stateMatProperty>     ::= "ambient"
                             | "diffuse"
                             | "specular"
                             | "emission"
                             | "shininess"

    <stateLightItem>       ::= "light" "[" <stateLightNumber> "]" "." 
                                 <stateLightProperty>

    <stateLightProperty>   ::= "ambient"
                             | "diffuse" 
                             | "specular"
                             | "position"
                             | "attenuation"
                             | "spot" "." <stateSpotProperty>
                             | "half"

    <stateSpotProperty>    ::= "direction" 

    <stateLightModelItem>  ::= "lightmodel" <stateLModProperty>

    <stateLModProperty>    ::= "." "ambient"
                             | <optFaceType> "." "scenecolor"

    <stateLightProdItem>   ::= "lightprod" "[" <stateLightNumber> "]" 
                                 <optFaceType> "." <stateLProdProperty>

    <stateLProdProperty>   ::= "ambient"
                             | "diffuse"
                             | "specular"

    <stateLightNumber>     ::= <integer> from 0 to MAX_LIGHTS-1

    <stateTexGenItem>      ::= "texgen" <optTexCoordNum> "." 
                                 <stateTexGenType> "." <stateTexGenCoord>

    <stateTexGenType>      ::= "eye"
                             | "object"

    <stateTexGenCoord>     ::= "s" 
                             | "t" 
                             | "r" 
                             | "q"

    <stateFogItem>         ::= "fog" "." <stateFogProperty>

    <stateFogProperty>     ::= "color" 
                             | "params" 

    <stateClipPlaneItem>   ::= "clip" "[" <stateClipPlaneNum> "]" "." "plane"

    <stateClipPlaneNum>    ::= <integer> from 0 to MAX_CLIP_PLANES-1

    <statePointItem>       ::= "point" "." <statePointProperty>

    <statePointProperty>   ::= "size"
                             | "attenuation"

    <stateMatrixRow>       ::= <stateMatrixItem> "." "row" "[" 
                                  <stateMatrixRowNum> "]"

    <stateMatrixRows>      ::= <stateMatrixItem> <optMatrixRows>

    <optMatrixRows>        ::= ""
                             | "." "row" "[" <stateMatrixRowNum> ".." 
                                  <stateMatrixRowNum> "]"

    <stateMatrixItem>      ::= "matrix" "." <stateMatrixName> 
                               <stateOptMatModifier>

    <stateOptMatModifier>  ::= ""
                             | "." <stateMatModifier>

    <stateMatModifier>     ::= "inverse" 
                             | "transpose" 
                             | "invtrans"

    <stateMatrixRowNum>    ::= <integer> from 0 to 3

    <stateMatrixName>      ::= "modelview" <stateOptModMatNum>
                             | "projection"
                             | "mvp"
                             | "texture" <optTexCoordNum>
                             | "palette" "[" <statePaletteMatNum> "]"
                             | "program" "[" <stateProgramMatNum> "]"
                             
    <stateOptModMatNum>    ::= ""
                             | "[" <stateModMatNum> "]"

    <stateModMatNum>       ::= <integer> from 0 to MAX_VERTEX_UNITS_ARB-1

    <statePaletteMatNum>   ::= <integer> from 0 to MAX_PALETTE_MATRICES_ARB-1

    <stateProgramMatNum>   ::= <integer> from 0 to MAX_PROGRAM_MATRICES_ARB-1

    <programSingleItem>    ::= <progEnvParam>
                             | <progLocalParam>

    <programMultipleItem>  ::= <progEnvParams>
                             | <progLocalParams>

    <progEnvParams>        ::= "program" "." "env" 
                                 "[" <progEnvParamNums> "]"

    <progEnvParamNums>     ::= <progEnvParamNum>
                             | <progEnvParamNum> ".." <progEnvParamNum>

    <progEnvParam>         ::= "program" "." "env" 
                                 "[" <progEnvParamNum> "]"

    <progLocalParams>      ::= "program" "." "local" 
                                 "[" <progLocalParamNums> "]"

    <progLocalParamNums>   ::= <progLocalParamNum>
                             | <progLocalParamNum> ".." <progLocalParamNum>

    <progLocalParam>       ::= "program" "." "local" 
                                 "[" <progLocalParamNum> "]"

    <progEnvParamNum>      ::= <integer> from 0 to
                               MAX_PROGRAM_ENV_PARAMETERS_ARB - 1

    <progLocalParamNum>    ::= <integer> from 0 to
                               MAX_PROGRAM_LOCAL_PARAMETERS_ARB - 1

    <paramConstDecl>       ::= <paramConstScalarDecl>
                             | <paramConstVector>

    <paramConstUse>        ::= <paramConstScalarUse>
                             | <paramConstVector>

    <paramConstScalarDecl> ::= <signedFloatConstant>

    <paramConstScalarUse>  ::= <floatConstant>

    <paramConstVector>     ::= "{" <signedFloatConstant> "}"
                             | "{" <signedFloatConstant> "," 
                                   <signedFloatConstant> "}"
                             | "{" <signedFloatConstant> "," 
                                   <signedFloatConstant> ","
                                   <signedFloatConstant> "}"
                             | "{" <signedFloatConstant> "," 
                                   <signedFloatConstant> ","
                                   <signedFloatConstant> "," 
                                   <signedFloatConstant> "}"

    <signedFloatConstant>  ::= <optionalSign> <floatConstant>

    <floatConstant>        ::= see text

    <optionalSign>         ::= ""
                             | "-"
                             | "+"

    <TEMP_statement>       ::= "TEMP" <varNameList>

    <ADDRESS_statement>    ::= "ADDRESS" <varNameList>

    <varNameList>          ::= <establishName>
                             | <establishName> "," <varNameList>

    <OUTPUT_statement>     ::= "OUTPUT" <establishName> "="
                                 <resultBinding>

    <resultBinding>        ::= "result" "." "position"
                             | "result" "." <resultColBinding>
                             | "result" "." "fogcoord"
                             | "result" "." "pointsize"
                             | "result" "." "texcoord" <optTexCoordNum>

    <resultColBinding>     ::= "color" <optFaceType> <optColorType>

    <optFaceType>          ::= ""
                             | "." "front"
                             | "." "back"

    <optColorType>         ::= ""
                             | "." "primary"
                             | "." "secondary"

    <optTexCoordNum>       ::= ""
                             | "[" <texCoordNum> "]"

    <texCoordNum>          ::= <integer> from 0 to MAX_TEXTURE_UNITS-1

    <ALIAS_statement>      ::= "ALIAS" <establishName> "="
                                 <establishedName>

    <establishName>        ::= <identifier>

    <establishedName>      ::= <identifier>

    <identifier>           ::= see text

    The <integer> rule matches an integer constant.  The integer consists
    of a sequence of one or more digits ("0" through "9").

    The <floatConstant> rule matches a floating-point constant consisting
    of an integer part, a decimal point, a fraction part, an "e" or
    "E", and an optionally signed integer exponent.  The integer and
    fraction parts both consist of a sequence of one or more digits ("0"
    through "9").  Either the integer part or the fraction parts (not
    both) may be missing; either the decimal point or the "e" (or "E")
    and the exponent (not both) may be missing.

    The <identifier> rule matches a sequence of one or more letters ("A"
    through "Z", "a" through "z"), digits ("0" through "9), underscores ("_"),
    or dollar signs ("$"); the first character must not be a number.  Upper
    and lower case letters are considered different (names are
    case-sensitive).  The following strings are reserved keywords and may not
    be used as identifiers:

        ABS, ADD, ADDRESS, ALIAS, ARL, ATTRIB, DP3, DP4, DPH, DST, END, EX2,
        EXP, FLR, FRC, LG2, LIT, LOG, MAD, MAX, MIN, MOV, MUL, OPTION, OUTPUT,
        PARAM, POW, RCP, RSQ, SGE, SLT, SUB, SWZ, TEMP, XPD, program, result,
        state, and vertex.

    The error INVALID_OPERATION is generated if a vertex program fails to load
    because it is not syntactically correct or for one of the semantic
    restrictions described in the following sections.

    A successfully loaded vertex program is parsed into a sequence of
    instructions.  Each instruction is identified by its tokenized name.  The
    operation of these instructions when executed is defined in section
    2.14.5.  A successfully loaded program string replaces the program string
    previously loaded into the specified program object.  If the OUT_OF_MEMORY
    error is generated by ProgramStringARB, no change is made to the previous
    contents of the current program object.


    Section 2.14.3,  Vertex Program Variables

    Vertex programs may access a number of different variables during their
    execution.  The following sections define the variables that can be
    declared and used by a vertex program.

    Explicit variable declarations allow a vertex program to establish a
    variable name that can be used to refer to a specified resource in
    subsequent instructions.  A vertex program will fail to load if it
    declares the same variable name more than once or if it refers to a
    variable name that has not been previously declared in the program string.

    Implicit variable declarations allow a vertex program to use the name of
    certain available resources by name.

    Section 2.14.3.1,  Vertex Attributes

    Vertex program attribute variables are a set of four-component
    floating-point vectors holding the attributes of the vertex being
    processed.  Vertex attribute variables are read-only during vertex program
    execution.

    Vertex attribute variables can be declared explicitly using the
    <ATTRIB_statement> grammar rule, or implicitly using the
    <vtxAttribBinding> grammar rule in an executable instruction.

    Each vertex attribute variable is bound to a single item of vertex state
    according to the <vtxAttrBinding> grammar rule.  The set of GL state that
    can be bound to a vertex attribute variable is given in Table X.2.  Vertex
    attribute variables are initialized at each vertex program invocation with
    the current values of the bound state.

      Vertex Attribute Binding  Components  Underlying State
      ------------------------  ----------  ------------------------------
      vertex.position           (x,y,z,w)   object coordinates
      vertex.weight             (w,w,w,w)   vertex weights 0-3
      vertex.weight[n]          (w,w,w,w)   vertex weights n-n+3
      vertex.normal             (x,y,z,1)   normal
      vertex.color              (r,g,b,a)   primary color
      vertex.color.primary      (r,g,b,a)   primary color
      vertex.color.secondary    (r,g,b,a)   secondary color
      vertex.fogcoord           (f,0,0,1)   fog coordinate
      vertex.texcoord           (s,t,r,q)   texture coordinate, unit 0
      vertex.texcoord[n]        (s,t,r,q)   texture coordinate, unit n
      vertex.matrixindex        (i,i,i,i)   vertex matrix indices 0-3
      vertex.matrixindex[n]     (i,i,i,i)   vertex matrix indices n-n+3
      vertex.attrib[n]          (x,y,z,w)   generic vertex attribute n

      Table X.2:  Vertex Attribute Bindings.  The "Components" column
      indicates the mapping of the state in the "Underlying State" column.
      Values of "0" or "1" in the "Components" column indicate the constants
      0.0 and 1.0, respectively.  Bindings containing "[n]" require an integer
      value of <n> to select an individual item.

    If a vertex attribute binding matches "vertex.position", the "x", "y", "z"
    and "w" components of the vertex attribute variable are filled with the
    "x", "y", "z", and "w" components, respectively, of the vertex position.

    If a vertex attribute binding matches "vertex.normal", the "x", "y", and
    "z" components of the vertex attribute variable are filled with the "x",
    "y", and "z" components, respectively, of the vertex normal.  The "w"
    component is filled with 1.

    If a vertex attribute binding matches "vertex.color" or
    "vertex.color.primary", the "x", "y", "z", and "w" components of the
    vertex attribute variable are filled with the "r", "g", "b", and "a"
    components, respectively, of the vertex color.

    If a vertex attribute binding matches "vertex.color.secondary", the "x",
    "y", "z", and "w" components of the vertex attribute variable are filled
    with the "r", "g", "b", and "a" components, respectively, of the vertex
    secondary color.

    If a vertex attribute binding matches "vertex.fogcoord", the "x" component
    of the vertex attribute variable is filled with the vertex fog coordinate.
    The "y", "z", and "w" coordinates are filled with 0, 0, and 1,
    respectively.

    If a vertex attribute binding matches "vertex.texcoord" or
    "vertex.texcoord[n]", the "x", "y", "z", and "w" components of the vertex
    attribute variable are filled with the "s", "t", "r", and "q" components,
    respectively, of the vertex texture coordinates for texture unit <n>.  If
    "[n]" is omitted, texture unit zero is used.

    If a vertex attribute binding matches "vertex.weight" or
    "vertex.weight[n]", the "x", "y", "z", and "w" components of the vertex
    attribute variable are filled with vertex weights <n> through <n>+3,
    respectively.  If "[n]" is omitted, weights zero through three are used.
    For the purposes of this binding, all weights supported by the
    implementation but not set by the application are set to zero, including
    the extra derived weight corresponding to the fixed-function
    WEIGHT_SUM_UNITY_ARB enable.  For components whose corresponding weight is
    not supported by the implementation (i.e., numbered MAX_VERTEX_UNITS_ARB
    or larger), "y" and "z" components are set to 0.0 and "w" components are
    set to 1.0.  A vertex program will fail to load if a vertex attribute
    binding specifies a weight number <n> that is greater than or equal to
    MAX_VERTEX_UNITS_ARB or is not divisible by four.

    If a vertex attribute binding matches "vertex.matrixindex" or
    "vertex.matrixindex[n]", the "x", "y", "z", and "w" components of the
    vertex attribute variable are filled with matrix indices <n> through <n>+3
    of the vertex, respectively.  If "[n]" is omitted, matrix indices zero
    through three are used.  For components whose corresponding matrix index
    is not supported by the implementation (i.e., numbered
    MAX_VERTEX_UNITS_ARB or larger), "y", and "z" components are set to 0.0
    and "w" components are set to 1.0.  A vertex program will fail to load if
    an attribute binding specifies a matrix index number <n> that is greater
    than or equal MAX_VERTEX_UNITS_ARB or is not divisible by four.

    If a vertex attribute binding matches "vertex.attrib[n]", the "x", "y",
    "z" and "w" components of the vertex attribute variable are filled with
    the "x", "y", "z", and "w" components, respectively, of generic vertex
    attribute <n>.  Note that "vertex.attrib[0]" and "vertex.position" are
    equivalent.

    As described in section 2.7, setting a generic vertex attribute may leave
    a corresponding conventional vertex attribute undefined, and vice versa.
    To prevent inadvertent use of attribute pairs with undefined attributes, a
    vertex program will fail to load if it binds both a conventional vertex
    attribute and a generic vertex attribute listed in the same row of Table
    X.2.1.

      Conventional Attribute Binding      Generic Attribute Binding
      ------------------------------      -------------------------
      vertex.position                     vertex.attrib[0]
      vertex.weight                       vertex.attrib[1]
      vertex.weight[0]                    vertex.attrib[1]
      vertex.normal                       vertex.attrib[2]
      vertex.color                        vertex.attrib[3]
      vertex.color.primary                vertex.attrib[3]
      vertex.color.secondary              vertex.attrib[4]        
      vertex.fogcoord                     vertex.attrib[5]
      vertex.texcoord                     vertex.attrib[8]
      vertex.texcoord[0]                  vertex.attrib[8]
      vertex.texcoord[1]                  vertex.attrib[9]
      vertex.texcoord[2]                  vertex.attrib[10]
      vertex.texcoord[3]                  vertex.attrib[11]
      vertex.texcoord[4]                  vertex.attrib[12]
      vertex.texcoord[5]                  vertex.attrib[13]
      vertex.texcoord[6]                  vertex.attrib[14]
      vertex.texcoord[7]                  vertex.attrib[15]
      vertex.texcoord[n]                  vertex.attrib[8+n]

      Table X.2.1:  Invalid Vertex Attribute Binding Pairs.  Vertex programs
      may not bind both attributes listed in any row.  The <n> in the last row
      matches the number of any valid texture unit.


    Section 2.14.3.2,  Vertex Program Parameters

    Vertex program parameter variables are a set of four-component
    floating-point vectors used as constants during vertex program execution.
    Vertex program parameters retain their values across vertex program
    invocations, although their values can change between invocations due to
    GL state changes.

    Single program parameter variables and arrays of program parameter
    variables can be declared explicitly using the <PARAM_statement> grammar
    rule.  Single program parameter variables can also be declared implicitly
    using the <paramSingleItemUse> grammar rule in an executable instruction.

    Each single program parameter variable is bound to a constant vector or to
    a GL state vector according to the <paramSingleInit> grammar rule.
    Individual items of a program parameter array are bound to constant
    vectors or GL state vectors according to the <programMultipleInit> grammar
    rule.  The set of GL state that can be bound to program parameter
    variables are given in Tables X.3.1 through X.3.8.


    Constant Bindings

    A program parameter variable can be bound to a scalar or vector constant
    using the <paramConstDecl> grammar rule (explicit declarations) or the
    <paramConstUse> grammar rule (implicit declarations).  

    If a program parameter binding matches the <paramConstScalarDecl> or
    <paramConstScalarUse> grammar rules, the corresponding program parameter
    variable is bound to the vector (X,X,X,X), where X is the value of the
    specified constant.  Note that the <paramConstScalarUse> grammar rule,
    used only in implicit declarations, allows only non-negative constants.
    This disambiguates cases like "-2", which could conceivably be taken to
    mean either the vector "(2,2,2,2)" with all components negated or
    "(-2,-2,-2,-2)" without negation.  Only the former interpretation is
    allowed by the grammar.

    If a program parameter binding matches <paramConstVector>, the
    corresponding program parameter variable is bound to the vector (X,Y,Z,W),
    where X, Y, Z, and W are the values corresponding to the first, second,
    third, and fourth match of <signedFloatConstant>.  If fewer than four
    constants are specified, Y, Z, and W assume the values 0.0, 0.0, and 1.0,
    if their respective constants are not specified.

    Program parameter variables initialized to constant values can never be
    modified.


    Program Environment/Local Parameter Bindings

      Binding                        Components  Underlying State
      -----------------------------  ----------  ----------------------------
      program.env[a]                 (x,y,z,w)   program environment 
                                                 parameter a
      program.local[a]               (x,y,z,w)   program local parameter a
      program.env[a..b]              (x,y,z,w)   program environment
                                                 parameters a through b
      program.local[a..b]            (x,y,z,w)   program local parameters
                                                 a through b

      Table X.3.1:  Program Environment/Local Parameter Bindings.  <a> and <b>
      indicate parameter numbers, where <a> must be less than or equal to <b>.

    If a program parameter binding matches "program.env[a]" or
    "program.local[a]", the four components of the program parameter variable
    are filled with the four components of program environment parameter <a>
    or program local parameter <a>, respectively.

    Additionally, for program parameter array bindings, "program.env[a..b]"
    and "program.local[a..b]" are equivalent to specifying program environment
    parameters <a> through <b> in order or program local parameters <a>
    through <b> in order, respectively.  In either case, a program will fail
    to load if <a> is greater than <b>.


    Material Property Bindings

      Binding                        Components  Underlying State
      -----------------------------  ----------  ----------------------------
      state.material.ambient         (r,g,b,a)   front ambient material color
      state.material.diffuse         (r,g,b,a)   front diffuse material color
      state.material.specular        (r,g,b,a)   front specular material color
      state.material.emission        (r,g,b,a)   front emissive material color
      state.material.shininess       (s,0,0,1)   front material shininess
      state.material.front.ambient   (r,g,b,a)   front ambient material color
      state.material.front.diffuse   (r,g,b,a)   front diffuse material color
      state.material.front.specular  (r,g,b,a)   front specular material color
      state.material.front.emission  (r,g,b,a)   front emissive material color
      state.material.front.shininess (s,0,0,1)   front material shininess
      state.material.back.ambient    (r,g,b,a)   back ambient material color
      state.material.back.diffuse    (r,g,b,a)   back diffuse material color
      state.material.back.specular   (r,g,b,a)   back specular material color
      state.material.back.emission   (r,g,b,a)   back emissive material color
      state.material.back.shininess  (s,0,0,1)   back material shininess

      Table X.3.2:  Material Property Bindings.  If a material face is not
      specified in the binding, the front property is used.

    If a program parameter binding matches any of the material properties
    listed in Table X.3.2, the program parameter variable is filled according
    to the table.  For ambient, diffuse, specular, or emissive colors, the
    "x", "y", "z", and "w" components are filled with the "r", "g", "b", and
    "a" components, respectively, of the corresponding material color.  For
    material shininess, the "x" component is filled with the material's
    specular exponent, and the "y", "z", and "w" components are filled with 0,
    0, and 1, respectively.  Bindings containing ".back" refer to the back
    material; all other bindings refer to the front material.

    Material properties can be changed inside a Begin/End pair, either
    directly by calling Material, or indirectly through color material.
    However, such property changes are not guaranteed to update program
    parameter bindings until the following End command.  Program parameter
    variables bound to material properties changed inside a Begin/End pair are
    undefined until the following End command.


    Light Property Bindings

      Binding                        Components  Underlying State
      -----------------------------  ----------  ----------------------------
      state.light[n].ambient         (r,g,b,a)   light n ambient color
      state.light[n].diffuse         (r,g,b,a)   light n diffuse color
      state.light[n].specular        (r,g,b,a)   light n specular color
      state.light[n].position        (x,y,z,w)   light n position
      state.light[n].attenuation     (a,b,c,e)   light n attenuation constants
                                                 and spot light exponent
      state.light[n].spot.direction  (x,y,z,c)   light n spot direction and
                                                 cutoff angle cosine
      state.light[n].half            (x,y,z,1)   light n infinite half-angle
      state.lightmodel.ambient       (r,g,b,a)   light model ambient color
      state.lightmodel.scenecolor    (r,g,b,a)   light model front scene color
      state.lightmodel.              (r,g,b,a)   light model front scene color
               front.scenecolor
      state.lightmodel.              (r,g,b,a)   light model back scene color
               back.scenecolor
      state.lightprod[n].ambient     (r,g,b,a)   light n / front material
                                                 ambient color product
      state.lightprod[n].diffuse     (r,g,b,a)   light n / front material
                                                 diffuse color product
      state.lightprod[n].specular    (r,g,b,a)   light n / front material
                                                 specular color product
      state.lightprod[n].            (r,g,b,a)   light n / front material
              front.ambient                      ambient color product
      state.lightprod[n].            (r,g,b,a)   light n / front material
              front.diffuse                      diffuse color product
      state.lightprod[n].            (r,g,b,a)   light n / front material
              front.specular                     specular color product
      state.lightprod[n].            (r,g,b,a)   light n / back material
              back.ambient                       ambient color product
      state.lightprod[n].            (r,g,b,a)   light n / back material
              back.diffuse                       diffuse color product
      state.lightprod[n].            (r,g,b,a)   light n / back material
              back.specular                      specular color product

      Table X.3.3: Light Property Bindings.  <n> indicates a light number.

    If a program parameter binding matches "state.light[n].ambient",
    "state.light[n].diffuse", or "state.light[n].specular", the "x", "y", "z",
    and "w" components of the program parameter variable are filled with the
    "r", "g", "b", and "a" components, respectively, of the corresponding
    light color.

    If a program parameter binding matches "state.light[n].position", the "x",
    "y", "z", and "w" components of the program parameter variable are filled
    with the "x", "y", "z", and "w" components, respectively, of the light
    position.
    
    If a program parameter binding matches "state.light[n].attenuation", the
    "x", "y", and "z" components of the program parameter variable are filled
    with the constant, linear, and quadratic attenuation parameters of the
    specified light, respectively (section 2.13.1).  The "w" component of the
    program parameter variable is filled with the spot light exponent of the
    specified light.

    If a program parameter binding matches "state.light[n].spot.direction",
    the "x", "y", and "z" components of the program parameter variable are
    filled with the "x", "y", and "z" components of the spot light direction
    of the specified light, respectively (section 2.13.1).  The "w" component
    of the program parameter variable is filled with the cosine of the spot
    light cutoff angle of the specified light.

    If a program parameter binding matches "state.light[n].half", the "x",
    "y", and "z" components of the program parameter variable are filled with
    the x, y, and z components, respectively, of the normalized infinite
    half-angle vector

      h_inf = || P + (0, 0, 1) ||.

    The "w" component is filled with 1.  In the computation of h_inf, P
    consists of the x, y, and z coordinates of the normalized vector from the
    eye position P_e to the eye-space light position P_pli (section 2.13.1).
    h_inf is defined to correspond to the normalized half-angle vector when
    using an infinite light (w coordinate of the position is zero) and an
    infinite viewer (v_bs is FALSE).  For local lights or a local viewer,
    h_inf is well-defined but does not match the normalized half-angle vector,
    which will vary depending on the vertex position.

    If a program parameter binding matches "state.lightmodel.ambient", the
    "x", "y", "z", and "w" components of the program parameter variable are
    filled with the "r", "g", "b", and "a" components of the light model
    ambient color, respectively.

    If a program parameter binding matches "state.lightmodel.scenecolor" or
    "state.lightmodel.front.scenecolor", the "x", "y", and "z" components of
    the program parameter variable are filled with the "r", "g", and "b"
    components respectively of the "front scene color"

      c_scene = a_cs * a_cm + e_cm,

    where a_cs is the light model ambient color, a_cm is the front ambient
    material color, and e_cm is the front emissive material color.  The "w"
    component of the program parameter variable is filled with the alpha
    component of the front diffuse material color.  If a program parameter
    binding matches "state.lightmodel.back.scenecolor", a similar back scene
    color, computed using back-facing material properties, is used.  The front
    and back scene colors match the values that would be assigned to vertices
    using conventional lighting if all lights were disabled.

    If a program parameter binding matches anything beginning with
    "state.lightprod[n]", the "x", "y", and "z" components of the program
    parameter variable are filled with the "r", "g", and "b" components,
    respectively, of the corresponding light product.  The three light product
    components are the products of the corresponding color components of the
    specified material property and the light color of the specified light
    (see Table X.3.3).  The "w" component of the program parameter variable is
    filled with the alpha component of the specified material property.

    Light products depend on material properties, which can be changed inside
    a Begin/End pair.  Such property changes are not guaranteed to take effect
    until the following End command.  Program parameter variables bound to
    light products whose corresponding material property changes inside a
    Begin/End pair are undefined until the following End command.


    Texture Coordinate Generation Property Bindings

      Binding                    Components  Underlying State
      -------------------------  ----------  ----------------------------
      state.texgen[n].eye.s      (a,b,c,d)   TexGen eye linear plane
                                             coefficients, s coord, unit n
      state.texgen[n].eye.t      (a,b,c,d)   TexGen eye linear plane
                                             coefficients, t coord, unit n
      state.texgen[n].eye.r      (a,b,c,d)   TexGen eye linear plane
                                             coefficients, r coord, unit n
      state.texgen[n].eye.q      (a,b,c,d)   TexGen eye linear plane
                                             coefficients, q coord, unit n
      state.texgen[n].object.s   (a,b,c,d)   TexGen object linear plane
                                             coefficients, s coord, unit n
      state.texgen[n].object.t   (a,b,c,d)   TexGen object linear plane
                                             coefficients, t coord, unit n
      state.texgen[n].object.r   (a,b,c,d)   TexGen object linear plane
                                             coefficients, r coord, unit n
      state.texgen[n].object.q   (a,b,c,d)   TexGen object linear plane
                                             coefficients, q coord, unit n

      Table X.3.4:  Texture Coordinate Generation Property Bindings.  "[n]" is
      optional -- texture unit <n> is used if specified; texture unit 0 is
      used otherwise.

    If a program parameter binding matches a set of TexGen plane coefficients,
    the "x", "y", "z", and "w" components of the program parameter variable
    are filled with the coefficients p1, p2, p3, and p4, respectively, for
    object linear coefficients, and the coefficents p1', p2', p3', and p4',
    respectively, for eye linear coefficients (section 2.10.4).


    Fog Property Bindings

      Binding                        Components  Underlying State
      -----------------------------  ----------  ----------------------------
      state.fog.color                (r,g,b,a)   RGB fog color (section 3.10)
      state.fog.params               (d,s,e,r)   fog density, linear start
                                                 and end, and 1/(end-start)
                                                 (section 3.10) 

      Table X.3.5:  Fog Property Bindings

    If a program parameter binding matches "state.fog.color", the "x", "y",
    "z", and "w" components of the program parameter variable are filled with
    the "r", "g", "b", and "a" components, respectively, of the fog color
    (section 3.10).

    If a program parameter binding matches "state.fog.params", the "x", "y",
    and "z" components of the program parameter variable are filled with the
    fog density, linear fog start, and linear fog end parameters (section
    3.10), respectively.  The "w" component is filled with 1/(end-start),
    where end and start are the linear fog end and start parameters,
    respectively.


    Clip Plane Property Bindings

      Binding                        Components  Underlying State
      -----------------------------  ----------  ----------------------------
      state.clip[n].plane            (a,b,c,d)   clip plane n coefficients

      Table X.3.6:  Clip Plane Property Bindings.  <n> specifies the clip
      plane number, and is required.

    If a program parameter binding matches "state.clip[n].plane", the "x",
    "y", "z", and "w" components of the program parameter variable are filled
    with the coefficients p1', p2', p3', and p4', respectively, of clip plane
    <n> (section 2.11).


    Point Property Bindings

      Binding                        Components  Underlying State
      -----------------------------  ----------  ----------------------------
      state.point.size               (s,n,x,f)   point size, min and max size
                                                 clamps, and fade threshold
                                                 (section 3.3) 
      state.point.attenuation        (a,b,c,1)   point size attenuation consts

      Table X.3.7:  Point Property Bindings

    If a program parameter binding matches "state.point.size", the "x", "y",
    "z", and "w" components of the program parameter variable are filled with
    the point size, minimum point size, maximum point size, and fade
    threshold, respectively (section 3.3).

    If a program parameter binding matches "state.point.attenuation", the "x",
    "y", and "z" components of the program parameter variable are filled with
    the constant, linear, and quadratic point size attenuation parameters (a,
    b, and c), respectively (section 3.3).  The "w" component is filled with
    1.


    Matrix Property Bindings

      Binding                               Underlying State
      ------------------------------------  ---------------------------
      * state.matrix.modelview[n]           modelview matrix n
        state.matrix.projection             projection matrix
        state.matrix.mvp                    modelview-projection matrix
      * state.matrix.texture[n]             texture matrix n
        state.matrix.palette[n]             modelview palette matrix n
        state.matrix.program[n]             program matrix n

      Table X.3.8:  Base Matrix Property Bindings.  The "[n]" syntax indicates
      a specific matrix number.  For modelview and texture matrices, a matrix
      number is optional, and matrix zero will be used if the matrix number is
      omitted.  These base bindings may further be modified by a
      inverse/transpose selector and a row selector.

    If the beginning of a program parameter binding matches any of the matrix
    binding names listed in Table X.3.8, the binding corresponds to a 4x4
    matrix.  If the parameter binding is followed by ".inverse", ".transpose",
    or ".invtrans" (<stateMatModifier> grammar rule), the inverse, transpose,
    or transpose of the inverse, respectively, of the matrix specified in
    Table X.3.8 is selected.  Otherwise, the matrix specified in Table X.3.8
    is selected.  If the specified matrix is poorly-conditioned (singular or
    nearly so), its inverse matrix is undefined.  The binding name
    "state.matrix.mvp" refers to the product of modelview matrix zero and the
    projection matrix, defined as

       MVP = P * M0,

    where P is the projection matrix and M0 is modelview matrix zero.

    If the selected matrix is followed by ".row[<a>]" (matching the
    <stateMatrixRow> grammar rule), the "x", "y", "z", and "w" components of
    the program parameter variable are filled with the four entries of row <a>
    of the selected matrix.  In the example,

      PARAM m0 = state.matrix.modelview[1].row[0];
      PARAM m1 = state.matrix.projection.transpose.row[3];

    the variable "m0" is set to the first row (row 0) of modelview matrix 1
    and "m1" is set to the last row (row 3) of the transpose of the projection
    matrix.

    For program parameter array bindings, multiple rows of the selected matrix
    can be bound via the <stateMatrixRows> grammar rule.  If the selected
    matrix binding is followed by ".row[<a>..<b>]", the result is equivalent
    to specifying matrix rows <a> through <b>, in order.  A program will fail
    to load if <a> is greater than <b>.  If no row selection is specified
    (<optMatrixRows> matches ""), matrix rows 0 through 3 are bound in order.
    In the example,

      PARAM m2[] = { state.matrix.program[0].row[1..2] };
      PARAM m3[] = { state.matrix.program[0].transpose };

    the array "m2" has two entries, containing rows 1 and 2 of program matrix
    zero, and "m3" has four entries, containing all four rows of the transpose
    of program matrix zero.


    Program Parameter Arrays

    A program parameter array variable can be declared explicitly by matching
    the <PARAM_multipleStmt> grammar rule.  Programs can optionally specify
    the number of individual program parameters in the array, using the
    <optArraySize> grammar rule.  Program parameter arrays may not be declared
    implicity.

    Individual parameter variables in a program parameter array are bound to
    GL state vectors or constant vectors as specified by the grammar rule
    <paramMultInitList>.  Each individual parameter in the array is bound in
    turn as described above.  

    The total number of entries in the array is equal to the number of
    parameters bound in the initializer list.  A vertex program that specifies
    an array size (<optArraySize> matches <integer>) that does not match the
    number of parameter bindings in the initialization list will fail to load.

    Program parameter array variables may be accessed using absolute
    addressing by matching the <progParamArrayAbs> grammar rule, or relative
    addressing by matching the <progParamArrayRel> grammar rule.

    Array accesses using absolute addressing are checked against the limits of
    the array.  If any vertex program instruction accesses a program parameter
    array using absolute addressing with an out-of-range index (greater than
    or equal to the size of the array), the vertex program will fail to load.

    Individual state vectors can have no more than one unique binding in any
    given program.  The GL will automatically combine multiple bindings of the
    same state vector into a single unique binding, except for the case where
    a state vector is bound multiple times in program parameter arrays
    accessed using relative addressing.  A vertex program will fail to load if
    any GL state vector is bound multiple times in a single array accessed
    using relative addressing or bound once in two or more arrays accessed
    using relative addressing.


    Section 2.14.3.3,  Vertex Program Temporaries

    Vertex program temporary variables are a set of four-component
    floating-point vectors used to hold temporary results during vertex
    program execution.  Temporaries do not persist between program
    invocations, and are undefined at the beginning of each vertex program
    invocation.

    Vertex program temporary variables can be declared explicitly using the
    <TEMP_statement> grammar rule.  Each such statement can declare one or
    more temporaries.  Vertex program temporary variables can not be declared
    implicitly.


    Section 2.14.3.4,  Vertex Program Results

    Vertex program result variables are a set of four-component floating-point
    vectors used to hold the final results of a vertex program.  Vertex
    program result variables are write-only during vertex program execution.

    Vertex program result variables can be declared explicitly using the
    <OUTPUT_statement> grammar rule, or implicitly using the <resultBinding>
    grammar rule in an executable instruction.  Each vertex program result
    variable is bound to a transformed vertex attribute used during primitive
    assembly and rasterization.  The set of vertex program result variable
    bindings is given in Table X.4.

      Binding                        Components  Description
      -----------------------------  ----------  ----------------------------
      result.position                (x,y,z,w)   position in clip coordinates
      result.color                   (r,g,b,a)   front-facing primary color
      result.color.primary           (r,g,b,a)   front-facing primary color
      result.color.secondary         (r,g,b,a)   front-facing secondary color
      result.color.front             (r,g,b,a)   front-facing primary color
      result.color.front.primary     (r,g,b,a)   front-facing primary color
      result.color.front.secondary   (r,g,b,a)   front-facing secondary color
      result.color.back              (r,g,b,a)   back-facing primary color
      result.color.back.primary      (r,g,b,a)   back-facing primary color
      result.color.back.secondary    (r,g,b,a)   back-facing secondary color
      result.fogcoord                (f,*,*,*)   fog coordinate
      result.pointsize               (s,*,*,*)   point size
      result.texcoord                (s,t,r,q)   texture coordinate, unit 0
      result.texcoord[n]             (s,t,r,q)   texture coordinate, unit n

      Table X.4:  Vertex Result Variable Bindings.  Components labeled "*" are
      unused.

    If a result variable binding matches "result.position", updates to the
    "x", "y", "z", and "w" components of the result variable modify the "x",
    "y", "z", and "w" components, respectively, of the transformed vertex's
    clip coordinates.  Final window coordinates will be generated for the
    vertex as described in section 2.14.4.4.

    If a result variable binding match begins with "result.color", updates to
    the "x", "y", "z", and "w" components of the result variable modify the
    "r", "g", "b", and "a" components, respectively, of the corresponding
    vertex color attribute in Table X.4.  Color bindings that do not specify
    "front" or "back" are consided to refer to front-facing colors.  Color
    bindings that do not specify "primary" or "secondary" are considered to
    refer to primary colors.

    If a result variable binding matches "result.fogcoord", updates to the "x"
    component of the result variable set the transformed vertex's fog
    coordinate.  Updates to the "y", "z", and "w" components of the result
    variable have no effect.

    If a result variable binding matches "result.pointsize", updates to the
    "x" component of the result variable set the transformed vertex's point
    size.  Updates to the "y", "z", and "w" components of the result variable
    have no effect.

    If a result variable binding matches "result.texcoord" or
    "result.texcoord[n]", updates to the "x", "y", "z", and "w" components of
    the result variable set the "s", "t", "r" and "q" components,
    respectively, of the transformed vertex's texture coordinates for texture
    unit <n>.  If "[n]" is omitted, texture unit zero is selected.

    When in vertex program mode, all attributes of a transformed vertex are
    undefined at each vertex program invocation.  Any results, or even
    individual components of results, that are not written to during vertex
    program execution remain undefined.


    Section 2.14.3.5,  Vertex Program Address Registers

    Vertex program address register variables are a set of four-component
    signed integer vectors where only the "x" component of the address
    registers is currently accessible.  Address registers are used as indices
    when performing relative addressing in program parameter arrays (section
    2.14.4.2).

    Vertex program address registers can be declared explicitly using the
    <ADDRESS_statement> grammar rule.  Each such statement can declare one or
    more address registers.  Vertex program address registers can not be
    declared implicitly.

    Vertex program address register variables are undefined at each vertex
    program invocation.  Address registers can be written by the ARL
    instruction (section 2.14.5.3), and will be read when a program uses
    relative addressing in program parameter arrays.


    Section 2.14.3.6, Vertex Program Aliases

    Vertex programs can create aliases by matching the <ALIAS_statement>
    grammar rule.  Aliases allow programs to use multiple variable names to
    refer to a single underlying variable.  For example, the statement

      ALIAS var1 = var0

    establishes a variable name named "var1".  Subsequent references to "var1"
    in the program text are treated as references to "var0".  The left hand
    side of an ALIAS statement must be a new variable name, and the right hand
    side must be an established variable name.

    Aliases are not considered variable declarations, so do not count against
    the limits on the number of variable declarations allowed in the program
    text.


    Section 2.14.3.7, Vertex Program Resource Limits

    The vertex program execution environment provides implementation-dependent
    resource limits on the number of instructions, temporary variable
    declarations, vertex attribute bindings, address register declarations,
    and program parameter bindings.  A program that exceeds any of these
    resource limits will fail to load.  The resource limits for vertex
    programs can be queried by calling GetProgramiv (section 6.1.12) with a
    target of VERTEX_PROGRAM_ARB.

    The limit on vertex program instructions can be queried with a <pname> of
    MAX_PROGRAM_INSTRUCTIONS_ARB, and must be at least 128.  Each instruction
    in the program (matching the <instruction> grammar rule) counts against
    this limit.

    The limit on vertex program temporary variable declarations can be queried
    with a <pname> of MAX_PROGRAM_TEMPORARIES_ARB, and must be at least 12.
    Each temporary declared in the program, using the <TEMP_statement> grammar
    rule, counts against this limit.  Aliases of declared temporaries do not.
    
    The limit on vertex program attribute bindings can be queried with a
    <pname> of MAX_PROGRAM_ATTRIBS_ARB and must be at least 16.  Each distinct
    vertex attribute bound explicitly or implicitly in the program counts
    against this limit; vertex attributes bound multiple times count only
    once.

    The limit on vertex program address register declarations can be queried
    with a <pname> of MAX_PROGRAM_ADDRESS_REGISTERS_ARB, and must be at least
    1.  Each address register declared in the program, using the
    <ADDRESS_statement> grammar rule, counts against this limit.
    
    The limit on vertex program parameter bindings can be queried with a
    <pname> of MAX_PROGRAM_PARAMETERS_ARB, and must be at least 96.  Each
    distinct GL state vector bound explicitly or implicitly in the program
    counts against this limit; GL state vectors bound multiple times count
    only once.  Each constant vector bound to an array accessed using relative
    addressing counts against this limit, even if the same constant vector is
    bound multiple times or in multiple arrays.  Every other constant vector
    bound in the program is counted if and only if an identical constant
    vector has not already been counted.  Two constant vectors are considered
    identical if the four component values are numerically equivalent.  Recall
    that scalar constants bound in a program are treated as vector constants
    with the scalar value replicated.  In the following code

           PARAM arr1[4] = { {1,2,3,4}, {1,2,3,4}, {4,4,4,4}, {5,6,7,8} };
           PARAM arr2[3] = { {1,2,3,4}, {5,6,7,8}, {0,1,2,3} };
           PARAM x = {4,3,2,1};
           PARAM y = {1,2,3,4};
           PARAM z = 4;
           PARAM r = {4,3,2,1};

    assume that arr1 is accessed using relative addressing but arr2 is not.
    The four constants in arr1 all count against the limit.  Only two other
    constants, {0,1,2,3} in arr2, and {4,3,2,1} in x, are counted; the other
    constants are identical to constants that had been previously counted.

    In addition to the limits described above, the GL provides a similar set
    of implementation-dependent native resource limits.  These limits,
    specified in section 6.1.12, provide guidance as to whether the program is
    small enough to use a "native" mode where vertex programs may be executed
    with higher performance.  The native resource limits and usage counts are
    implementation-dependent and may not exactly correspond to limits and
    counts described above.  In particular, native resource consumption may be
    reduced by program optimizations performed by the GL, or increased due to
    emulation of non-native instructions.  Programs that satisfy the program
    resource limits described above, but whose native resource usage exceeds
    one or more native resource limits, are guaranteed to load but may execute
    suboptimally.

    To assist in resource counting, the GL additionally provides GetProgram
    queries to determine the resource usage and native resource usage of the
    currently bound program, and to determine whether the bound program
    exceeds any native resource limit.


    Section 2.14.4,  Vertex Program Execution Environment

    If vertex program mode is enabled, the currently bound vertex program is
    executed when a vertex is specified directly through the Vertex command,
    indirectly through vertex arrays or evaluators (section 5.1), or when the
    current raster position is updated.  

    If vertex program mode is enabled and the currently bound program object
    does not contain a valid vertex program, the error INVALID_OPERATION will
    be generated by Begin, RasterPos, and any command that implicitly calls
    Begin (e.g., DrawArrays).

    Vertex programs execute a sequence of instructions without
    branching.  Vertex programs begin by executing the first instruction in
    the program, and execute instructions in the order specified in the
    program until the last instruction is completed.
    
    There are twenty-seven vertex program instructions.  The instructions and
    their respective input and output parameters are summarized in Table X.5.

      Instruction    Inputs  Output   Description
      -----------    ------  ------   --------------------------------
      ABS            v       v        absolute value
      ADD            v,v     v        add
      ARL            s       a        address register load
      DP3            v,v     ssss     3-component dot product
      DP4            v,v     ssss     4-component dot product
      DPH            v,v     ssss     homogeneous dot product
      DST            v,v     v        distance vector
      EX2            s       ssss     exponential base 2
      EXP            s       v        exponential base 2 (approximate)
      FLR            v       v        floor
      FRC            v       v        fraction
      LG2            s       ssss     logarithm base 2
      LIT            v       v        compute light coefficients
      LOG            s       v        logarithm base 2 (approximate)
      MAD            v,v,v   v        multiply and add
      MAX            v,v     v        maximum
      MIN            v,v     v        minimum
      MOV            v       v        move
      MUL            v,v     v        multiply
      POW            s,s     ssss     exponentiate
      RCP            s       ssss     reciprocal
      RSQ            s       ssss     reciprocal square root
      SGE            v,v     v        set on greater than or equal
      SLT            v,v     v        set on less than
      SUB            v,v     v        subtract
      SWZ            v       v        extended swizzle
      XPD            v,v     v        cross product

      Table X.5:  Summary of vertex program instructions.  "v" indicates a
      floating-point vector input or output, "s" indicates a floating-point
      scalar input, "ssss" indicates a scalar output replicated across a
      4-component result vector, and "a" indicates a single address register
      component.


    Section 2.14.4.1, Vertex Program Operands

    Most vertex program instructions operate on floating-point vectors or
    scalars, as indicated by the grammar rules <swizzleSrcReg> and
    <scalarSrcReg>, respectively.

    Vector and scalar operands can be obtained from vertex attribute, program
    parameter, or temporary registers, as indicated by the <srcReg> rule.  For
    scalar operands, a single vector component is selected by the
    <scalarSuffix> rule, where the characters "x", "y", "z", and "w" select
    the x, y, z, and w components, respectively, of the vector.

    Vector operands can be swizzled according to the <swizzleSuffix> rule.  In
    its most general form, the <swizzleSuffix> rule matches the pattern
    ".????" where each question mark is replaced with one of "x", "y", "z", or
    "w".  For such patterns, the x, y, z, and w components of the operand are
    taken from the vector components named by the first, second, third, and
    fourth character of the pattern, respectively.  For example, if the
    swizzle suffix is ".yzzx" and the specified source contains {2,8,9,0}, the
    swizzled operand used by the instruction is {8,9,9,2}.

    If the <swizzleSuffix> rule matches "", it is treated as though it were
    ".xyzw".  If the <swizzleSuffix> rule matches (ignoring whitespace) ".x",
    ".y", ".z", or ".w", these are treated the same as ".xxxx", ".yyyy",
    ".zzzz", and ".wwww" respectively.

    Floating-point scalar or vector operands can optionally be negated
    according to the <optionalSign> rule in <scalarSrcReg> and
    <swizzleSrcReg>.  If the <optionalSign> matches "-", each operand or
    operand component is negated.

    The following pseudo-code spells out the operand generation process.  In
    the example, "float" is a floating-point scalar type, while "floatVec" is
    a four-component vector.  "source" refers to the register used for the
    operand, matching the <srcReg> rule.  "negate" is TRUE if the
    <optionalSign> rule in <scalarSrcReg> or <swizzleSrcReg> matches "-" and
    FALSE otherwise.  The ".c***", ".*c**", ".**c*", ".***c" modifiers refer
    to the x, y, z, and w components obtained by the swizzle operation; the
    ".c" modifier refers to the single component selected for a scalar load.

      floatVec VectorLoad(floatVec source)
      {
          floatVec operand;

          operand.x = source.c***;
          operand.y = source.*c**;
          operand.z = source.**c*;
          operand.w = source.***c;
          if (negate) {
             operand.x = -operand.x;
             operand.y = -operand.y;
             operand.z = -operand.z;
             operand.w = -operand.w;
          }

          return operand;
      }

      float ScalarLoad(floatVec source) 
      {
          float operand;

          operand = source.c;
          if (negate) {
            operand = -operand;
          }

          return operand;
      }

    Section 2.14.4.2,  Vertex Program Parameter Arrays

    A vertex program can load a single element of a program parameter array
    using either absolute or relative addressing.  Program parameter arrays
    are accessed when the <progParamArray> rule is matched.

    Absolute addressing is used when the <progParamArrayMem> grammar rule
    matches <progParamArrayAbs>.  When using absolute addressing, the offset
    of the selected entry in the array is given by the number matching
    <progParamRegNum>.

    Relative addressing is used when the <progParamArrayMem> grammar rule
    matches <progParamArrayRel>.  When using relative addressing, the offset
    of the selected entry in the array is computed by adding the address
    register component specified by the <addrReg> and <addrComponent> rules to
    the positive or negative offset specified by the <addrRegRelOffset> rule.
    If <addrRegRelOffset> matches "", no fixed offset is added to the address
    register component.  If the computed offset is negative or exceeds the
    size of the array, the results of the access are undefined, but may not
    lead to program or GL termination.

    The following pseudo-code spells out the process of loading a program
    parameter from an array.  "addrReg" refers to the address register
    component used for relative addressing, "absolute" is TRUE if the operand
    uses absolute addressing and FALSE otherwise.  "paramNumber" is the
    program parameter number for absolute addressing; "paramOffset" is the
    constant program parameter offset for relative addressing.  "paramArray"
    is the parameter array that matches the <progParamArray> rule.

      floatVec ProgramParameterLoad(int addrReg)
      {
        int index;
        
        if (absolute) {
          index = paramNumber;
        } else {
          index = addrReg + paramOffset
        }

        return paramArray[index];
      }

    Relative addressing can only be used for accessing program parameter
    arrays.


    Section 2.14.4.3,  Vertex Program Destination Register Update

    Most vertex program instructions write a 4-component result vector to a
    single temporary or vertex result register.  Writes to individual
    components of the destination register are controlled by individual
    component write masks specified as part of the instruction.

    The component write mask is specified by the <optionalMask> rule found in
    the <maskedDstReg> rule.  If the optional mask is "", all components are
    enabled.  Otherwise, the optional mask names the individual components to
    enable.  The characters "x", "y", "z", and "w" match the x, y, z, and w
    components respectively.  For example, an optional mask of ".xzw"
    indicates that the x, z, and w components should be enabled for writing
    but the y component should not.  The grammar requires that the destination
    register mask components must be listed in "xyzw" order.

    Each component of the destination register is updated with the result of
    the vertex program instruction if and only if the component is enabled for
    writes by the component write mask.  Otherwise, the component of the
    destination register remains unchanged.

    The following pseudocode illustrates the process of writing a result
    vector to the destination register.  In the pseudocode, "instrmask" refers
    to the component write mask given by the <optionalMask> rule.  "result"
    and "destination" refer to the result vector and the register selected by
    <dstReg>, respectively.

      void UpdateDestination(floatVec destination, floatVec result)
      {
          floatVec merged;

          // Merge the converted result into the destination register, under
          // control of the compile-time write mask.
          merged = destination;
          if (instrMask.x) {
              merged.x = result.x;
          }
          if (instrMask.y) {
              merged.y = result.y;
          }
          if (instrMask.z) {
              merged.z = result.z;
          }
          if (instrMask.w) {
              merged.w = result.w;
          }

          // Write out the new destination register.
          destination = merged;
      }

    The "ARL" instruction updates the single address register component
    similarly; the grammar is designed so that it writes to only the "x"
    component of an address register variable.


    Section 2.14.4.4,  Vertex Program Result Processing

    As a vertex program executes, it will write to one or more result
    registers that are mapped to transformed vertex attributes.  When a vertex
    program completes, the transformed vertex attributes are used to generate
    primitives.

    The clip coordinates written to "result.position" are used to generate
    normalized device coordinates and window coordinates for the vertex in the
    manner described section 2.10.

    Transformed vertices are then assembled into primitives and clipped as
    described in section 2.11.

    The selection between front-facing and back-facing color attributes
    depends on the primitive to which the vertex belongs.  If the primitive is
    a point or a line segment, or if vertex program two-sided color mode is
    disabled, the front-facing colors are always selected.  If it is a polygon
    and two-sided color mode is enabled, then the selection is performed in
    exactly the same way as in two-sided lighting mode (section 2.13.1).
    Vertex program two-sided color mode is enabled and disabled by calling
    Enable or Disable with the symbolic value VERTEX_PROGRAM_TWO_SIDE_ARB.

    Finally, as primitives are assembled, color clamping (section 2.13.6),
    flatshading (section 2.13.7), color, attribute clipping (section 2.13.8),
    and final color processing (section 2.13.9) operations are applied to the
    transformed vertices.


    Section 2.14.4.5,  Vertex Program Options

    The <optionSequence> grammar rule provides a mechanism for programs to
    indicate that one or more extended language features are used by the
    program.  All program options used by the program must be declared at the
    beginning of the program string.  Each program option specified in a
    program string will modify the syntactic or semantic rules used to
    interpet the program and the execution environment used to execute the
    program.  Program options not present in the program string are ignored,
    even if they are supported by the GL.

    The <identifier> token in the <option> rule must match the name of a
    program option supported by the implementation.  To avoid option name
    conflicts, option identifiers are required to begin with a vendor prefix.
    A program will fail to load if it specifies a program option not supported
    by the GL.

    Vertex program options should confine their semantic changes to the domain
    of vertex programs.  Support for a vertex program option should not change
    the specification and behavior of vertex programs not requesting use of
    that option.

    2.14.4.5.1,  Position-Invariant Vertex Program Option

    If a vertex program specifies the "ARB_position_invariant" option, the
    program is used to generate all transformed vertex attributes except for
    position.  Instead, clip coordinates are computed as specified in section
    2.10.  Additionally, user clipping is performed as described in section
    2.11.  Use of position-invariant vertex programs should generally
    guarantee that the transformed position of a vertex should be the same
    whether vertex program mode is enabled or disabled, allowing for correct
    mixed multi-pass rendering semantics.

    When the position-invariant option is specified in a vertex program,
    vertex programs can no longer produced a transformed position.  The
    <resultBinding> rule is modified to remove "result.position" from the list
    of token sequences matching the rule.  A semantic restriction is added to
    indicate that a vertex program will fail to load if the number of
    instructions it contains exceeds the implementation-dependent limit minus
    four.


    Section 2.14.5,  Vertex Program Instruction Set

    The following sections describe the set of supported vertex program
    instructions.  Each section contains pseudocode describing the
    instruction.  Instructions will have up to three operands, referred to as
    "op0", "op1", and "op2".  The operands are loaded using the mechanisms
    specified in section 2.14.4.1.  The variables "tmp", "tmp0", "tmp1", and
    "tmp2" describe scalars or vectors used to hold intermediate results in
    the instruction.  Most instructions will generate a result vector called
    "result".  The result vector is then written to the destination register
    specified in the instruction as described in section 2.14.4.3.


    Section 2.14.5.1,  ABS:  Absolute Value

    The ABS instruction performs a component-wise absolute value operation on
    the single operand to yield a result vector.

      tmp = VectorLoad(op0); 
      result.x = fabs(tmp.x);
      result.y = fabs(tmp.y);
      result.z = fabs(tmp.z);
      result.w = fabs(tmp.w);


    Section 2.14.5.2,  ADD:  Add

    The ADD instruction performs a component-wise add of the two operands to
    yield a result vector.

      tmp0 = VectorLoad(op0);
      tmp1 = VectorLoad(op1);
      result.x = tmp0.x + tmp1.x;
      result.y = tmp0.y + tmp1.y;
      result.z = tmp0.z + tmp1.z;
      result.w = tmp0.w + tmp1.w;

    The following rules apply to addition:

      1. <x> + <y> == <y> + <x>, for all <x> and <y>.
      2. <x> + 0.0 == <x>, for all <x>.


    Section 2.14.5.3,  ARL:  Address Register Load

    The ARL instruction loads a single scalar operand and performs a floor
    operation to generate a signed integer scalar result:

        result = floor(ScalarLoad(op0));

    The floor operation returns the largest integer less than or equal to the
    operand.  For example floor(-1.7) = -2.0, floor(+1.0) = +1.0, and
    floor(+3.7) = +3.0.


    Section 2.14.5.4,  DP3:  Three-Component Dot Product

    The DP3 instruction computes a three-component dot product of the two
    operands (using the x, y, and z components) and replicates the dot product
    to all four components of the result vector.

      tmp0 = VectorLoad(op0);
      tmp1 = VectorLoad(op1);
      dot = (tmp0.x * tmp1.x) + (tmp0.y * tmp1.y) + 
            (tmp0.z * tmp1.z);
      result.x = dot;
      result.y = dot;
      result.z = dot;
      result.w = dot;


    Section 2.14.5.5,  DP4:  Four-Component Dot Product

    The DP4 instruction computes a four-component dot product of the two
    operands and replicates the dot product to all four components of the
    result vector.

      tmp0 = VectorLoad(op0);
      tmp1 = VectorLoad(op1):
      dot = (tmp0.x * tmp1.x) + (tmp0.y * tmp1.y) + 
            (tmp0.z * tmp1.z) + (tmp0.w * tmp1.w);
      result.x = dot;
      result.y = dot;
      result.z = dot;
      result.w = dot;


    Section 2.14.5.6,  DPH:  Homogeneous Dot Product

    The DPH instruction computes a three-component dot product of the two
    operands (using the x, y, and z components), adds the w component of the
    second operand, and replicates the sum to all four components of the
    result vector.  This is equivalent to a four-component dot product where
    the w component of the first operand is forced to 1.0.

      tmp0 = VectorLoad(op0);
      tmp1 = VectorLoad(op1):
      dot = (tmp0.x * tmp1.x) + (tmp0.y * tmp1.y) + 
            (tmp0.z * tmp1.z) + tmp1.w;
      result.x = dot;
      result.y = dot;
      result.z = dot;
      result.w = dot;


    Section 2.14.5.7,  DST:  Distance Vector

    The DST instruction computes a distance vector from two specially-
    formatted operands.  The first operand should be of the form [NA, d^2,
    d^2, NA] and the second operand should be of the form [NA, 1/d, NA, 1/d],
    where NA values are not relevant to the calculation and d is a vector
    length.  If both vectors satisfy these conditions, the result vector will
    be of the form [1.0, d, d^2, 1/d].

    The exact behavior is specified in the following pseudo-code:

      tmp0 = VectorLoad(op0);
      tmp1 = VectorLoad(op1);
      result.x = 1.0;
      result.y = tmp0.y * tmp1.y;
      result.z = tmp0.z;
      result.w = tmp1.w;

    Given an arbitrary vector, d^2 can be obtained using the DP3 instruction
    (using the same vector for both operands) and 1/d can be obtained from d^2
    using the RSQ instruction.

    This distance vector is useful for per-vertex light attenuation
    calculations:  a DP3 operation using the distance vector and an
    attenuation constants vector as operands will yield the attenuation
    factor.


    Section 2.14.5.8,  EX2:  Exponential Base 2

    The EX2 instruction approximates 2 raised to the power of the scalar
    operand and replicates the approximation to all four components of the
    result vector.

      tmp = ScalarLoad(op0);
      result.x = Approx2ToX(tmp);
      result.y = Approx2ToX(tmp);
      result.z = Approx2ToX(tmp);
      result.w = Approx2ToX(tmp);


    Section 2.14.5.9,  EXP:  Exponential Base 2 (approximate)

    The EXP instruction computes a rough approximation of 2 raised to the
    power of the scalar operand.  The approximation is returned in the "z"
    component of the result vector.  A vertex program can also use the "x" and
    "y" components of the result vector to generate a more accurate
    approximation by evaluating

        result.x * f(result.y),
    
    where f(x) is a user-defined function that approximates 2^x over the
    domain [0.0, 1.0).  The "w" component of the result vector is always 1.0.
    
    The exact behavior is specified in the following pseudo-code:

      tmp = ScalarLoad(op0);
      result.x = 2^floor(tmp);
      result.y = tmp - floor(tmp);
      result.z = RoughApprox2ToX(tmp);
      result.w = 1.0;

    The approximation function is accurate to at least 10 bits:

      | RoughApprox2ToX(x) - 2^x | < 1.0 / 2^11, if 0.0 <= x < 1.0,

    and, in general,
   
      | RoughApprox2ToX(x) - 2^x | < (1.0 / 2^11) * (2^floor(x)).


    Section 2.14.5.10,  FLR:  Floor

    The FLR instruction performs a component-wise floor operation on the
    operand to generate a result vector.  The floor of a value is defined as
    the largest integer less than or equal to the value.  The floor of 2.3 is
    2.0; the floor of -3.6 is -4.0.

      tmp = VectorLoad(op0);
      result.x = floor(tmp.x);
      result.y = floor(tmp.y);
      result.z = floor(tmp.z);
      result.w = floor(tmp.w);


    Section 2.14.5.11,  FRC:  Fraction

    The FRC instruction extracts the fractional portion of each component of
    the operand to generate a result vector.  The fractional portion of a
    component is defined as the result after subtracting off the floor of the
    component (see FLR), and is always in the range [0.0, 1.0).

    For negative values, the fractional portion is NOT the number written to
    the right of the decimal point -- the fractional portion of -1.7 is not
    0.7 -- it is 0.3.  0.3 is produced by subtracting the floor of -1.7 (-2.0)
    from -1.7.

      tmp = VectorLoad(op0);
      result.x = fraction(tmp.x);
      result.y = fraction(tmp.y);
      result.z = fraction(tmp.z);
      result.w = fraction(tmp.w);


    Section 2.14.5.12,  LG2:  Logarithm Base 2

    The LG2 instruction approximates the base 2 logarithm of the scalar
    operand and replicates it to all four components of the result vector.

      tmp = ScalarLoad(op0);
      result.x = ApproxLog2(tmp);
      result.y = ApproxLog2(tmp);
      result.z = ApproxLog2(tmp);
      result.w = ApproxLog2(tmp);

    If the scalar operand is zero or negative, the result is undefined.


    Section 2.14.5.13,  LIT:  Light Coefficients

    The LIT instruction accelerates per-vertex lighting by computing lighting
    coefficients for ambient, diffuse, and specular light contributions.  The
    "x" component of the single operand is assumed to hold a diffuse dot
    product (n dot VP_pli, as in the vertex lighting equations in Section
    2.13.1).  The "y" component of the operand is assumed to hold a specular
    dot product (n dot h_i).  The "w" component of the operand is assumed to
    hold the specular exponent of the material (s_rm), and is clamped to the
    range (-128, +128) exclusive.

    The "x" component of the result vector receives the value that should be
    multiplied by the ambient light/material product (always 1.0).  The "y"
    component of the result vector receives the value that should be
    multiplied by the diffuse light/material product (n dot VP_pli).  The "z"
    component of the result vector receives the value that should be
    multiplied by the specular light/material product (f_i * (n dot h_i) ^
    s_rm).  The "w" component of the result is the constant 1.0.

    Negative diffuse and specular dot products are clamped to 0.0, as is done
    in the standard per-vertex lighting operations.  In addition, if the
    diffuse dot product is zero or negative, the specular coefficient is
    forced to zero.

      tmp = VectorLoad(op0);
      if (tmp.x < 0) tmp.x = 0;
      if (tmp.y < 0) tmp.y = 0;
      if (tmp.w < -(128.0-epsilon)) tmp.w = -(128.0-epsilon);
      else if (tmp.w > 128-epsilon) tmp.w = 128-epsilon;
      result.x = 1.0;
      result.y = tmp.x;
      result.z = (tmp.x > 0) ? RoughApproxPower(tmp.y, tmp.w) : 0.0;
      result.w = 1.0;

    The exponentiation approximation function may be defined in terms of the
    base 2 exponentiation and logarithm approximation operations in the EXP
    and LOG instructions, where

      RoughApproxPower(a,b) = RoughApproxExp2(b * RoughApproxLog2(a)).

    In particular, the approximation may not be any more accurate than the
    underlying EXP and LOG operations.

    Also, since 0^0 is defined to be 1, RoughApproxPower(0.0, 0.0) will
    produce 1.0.


    Section 2.14.5.14,  LOG:  Logarithm Base 2 (approximate)

    The LOG instruction computes a rough approximation of the base 2 logarithm
    of the absolute value of the scalar operand.  The approximation is
    returned in the "z" component of the result vector.  A vertex program can
    also use the "x" and "y" components of the result vector to generate a
    more accurate approximation by evaluating

        result.x + f(result.y),
    
    where f(x) is a user-defined function that approximates 2^x over the
    domain [1.0, 2.0).  The "w" component of the result vector is always 1.0.

    The exact behavior is specified in the following pseudo-code:

      tmp = fabs(ScalarLoad(op0));
      result.x = floor(log2(tmp));
      result.y = tmp / 2^(floor(log2(tmp)));
      result.z = RoughApproxLog2(tmp);
      result.w = 1.0;
   
    Here, "floor(log2(tmp))" refers to the floor of the exact logarithm, which
    can be easily computed for standard floating-point representations.  The
    approximation function is accurate to at least 10 bits:

      | RoughApproxLog2(x) - log_2(x) | < 1.0 / 2^11.


    Section 2.14.5.15,  MAD:  Multiply and Add

    The MAD instruction performs a component-wise multiply of the first two
    operands, and then does a component-wise add of the product to the third
    operand to yield a result vector.

      tmp0 = VectorLoad(op0);
      tmp1 = VectorLoad(op1);
      tmp2 = VectorLoad(op2);
      result.x = tmp0.x * tmp1.x + tmp2.x;
      result.y = tmp0.y * tmp1.y + tmp2.y;
      result.z = tmp0.z * tmp1.z + tmp2.z;
      result.w = tmp0.w * tmp1.w + tmp2.w;

    The multiplication and addition operations in this instruction are subject
    to the same rules as described for the MUL and ADD instructions.


    Section 2.14.5.16,  MAX:  Maximum

    The MAX instruction computes component-wise maximums of the values in the
    two operands to yield a result vector.

      tmp0 = VectorLoad(op0);
      tmp1 = VectorLoad(op1);
      result.x = (tmp0.x > tmp1.x) ? tmp0.x : tmp1.x;
      result.y = (tmp0.y > tmp1.y) ? tmp0.y : tmp1.y;
      result.z = (tmp0.z > tmp1.z) ? tmp0.z : tmp1.z;
      result.w = (tmp0.w > tmp1.w) ? tmp0.w : tmp1.w;


    Section 2.14.5.17,  MIN:  Minimum

    The MIN instruction computes component-wise minimums of the values in the
    two operands to yield a result vector.

      tmp0 = VectorLoad(op0);
      tmp1 = VectorLoad(op1);
      result.x = (tmp0.x > tmp1.x) ? tmp1.x : tmp0.x;
      result.y = (tmp0.y > tmp1.y) ? tmp1.y : tmp0.y;
      result.z = (tmp0.z > tmp1.z) ? tmp1.z : tmp0.z;
      result.w = (tmp0.w > tmp1.w) ? tmp1.w : tmp0.w;


    Section 2.14.5.18,  MOV:  Move

    The MOV instruction copies the value of the operand to yield a result
    vector.

      result = VectorLoad(op0);


    Section 2.14.5.19,  MUL:  Multiply

    The MUL instruction performs a component-wise multiply of the two operands
    to yield a result vector.

      tmp0 = VectorLoad(op0);
      tmp1 = VectorLoad(op1);
      result.x = tmp0.x * tmp1.x;
      result.y = tmp0.y * tmp1.y;
      result.z = tmp0.z * tmp1.z;
      result.w = tmp0.w * tmp1.w;

    The following rules apply to multiplication:

      1. <x> * <y> == <y> * <x>, for all <x> and <y>.
      2. +/-0.0 * <x> = +/-0.0, at least for all <x> that correspond to
         representable numbers (IEEE "not a number" and "infinity" encodings
         may be exceptions).
      3. +1.0 * <x> = <x>, for all <x>.

    Multiplication by zero and one should be invariant, as it may be used to
    evaluate conditional expressions without branching.


    Section 2.14.5.20,  POW:  Exponentiate

    The POW instruction approximates the value of the first scalar operand
    raised to the power of the second scalar operand and replicates it to all
    four components of the result vector.

      tmp0 = ScalarLoad(op0);
      tmp1 = ScalarLoad(op1);
      result.x = ApproxPower(tmp0, tmp1);
      result.y = ApproxPower(tmp0, tmp1);
      result.z = ApproxPower(tmp0, tmp1);
      result.w = ApproxPower(tmp0, tmp1);

    The exponentiation approximation function may be implemented using the
    base 2 exponentiation and logarithm approximation operations in the EX2
    and LG2 instructions.  In particular,

      ApproxPower(a,b) = ApproxExp2(b * ApproxLog2(a)).

    Note that a logarithm may be involved even for cases where the exponent is
    an integer.  This means that it may not be possible to exponentiate
    correctly with a negative base.  In constrast, it is possible in a
    "normal" mathematical formulation to raise negative numbers to integral
    powers (e.g., (-3)^2== 9, and (-0.5)^-2==4).


    Section 2.14.5.21,  RCP:  Reciprocal

    The RCP instruction approximates the reciprocal of the scalar operand and
    replicates it to all four components of the result vector.

      tmp = ScalarLoad(op0);
      result.x = ApproxReciprocal(tmp);
      result.y = ApproxReciprocal(tmp);
      result.z = ApproxReciprocal(tmp);
      result.w = ApproxReciprocal(tmp);

    The following rule applies to reciprocation:

      1. ApproxReciprocal(+1.0) = +1.0.


    Section 2.14.5.22,  RSQ:  Reciprocal Square Root

    The RSQ instruction approximates the reciprocal of the square root of the
    absolute value of the scalar operand and replicates it to all four
    components of the result vector.

      tmp = fabs(ScalarLoad(op0));
      result.x = ApproxRSQRT(tmp);
      result.y = ApproxRSQRT(tmp);
      result.z = ApproxRSQRT(tmp);
      result.w = ApproxRSQRT(tmp);


    Section 2.14.5.23,  SGE:  Set On Greater or Equal Than

    The SGE instruction performs a component-wise comparison of the two
    operands.  Each component of the result vector is 1.0 if the corresponding
    component of the first operands is greater than or equal that of the
    second, and 0.0 otherwise.

      tmp0 = VectorLoad(op0);
      tmp1 = VectorLoad(op1);
      result.x = (tmp0.x >= tmp1.x) ? 1.0 : 0.0;
      result.y = (tmp0.y >= tmp1.y) ? 1.0 : 0.0;
      result.z = (tmp0.z >= tmp1.z) ? 1.0 : 0.0;
      result.w = (tmp0.w >= tmp1.w) ? 1.0 : 0.0;


    Section 2.14.5.24,  SLT:  Set On Less Than

    The SLT instruction performs a component-wise comparison of the two
    operands.  Each component of the result vector is 1.0 if the corresponding
    component of the first operand is less than that of the second, and 0.0
    otherwise.

      tmp0 = VectorLoad(op0);
      tmp1 = VectorLoad(op1);
      result.x = (tmp0.x < tmp1.x) ? 1.0 : 0.0;
      result.y = (tmp0.y < tmp1.y) ? 1.0 : 0.0;
      result.z = (tmp0.z < tmp1.z) ? 1.0 : 0.0;
      result.w = (tmp0.w < tmp1.w) ? 1.0 : 0.0;


    Section 2.14.5.25,  SUB:  Subtract

    The SUB instruction performs a component-wise subtraction of the second
    operand from the first to yield a result vector.

      tmp0 = VectorLoad(op0);
      tmp1 = VectorLoad(op1);
      result.x = tmp0.x - tmp1.x;
      result.y = tmp0.y - tmp1.y;
      result.z = tmp0.z - tmp1.z;
      result.w = tmp0.w - tmp1.w;


    Section 2.14.5.26,  SWZ:  Extended Swizzle

    The SWZ instruction loads the single vector operand, and performs a
    swizzle operation more powerful than that provided for loading normal
    vector operands to yield an instruction vector.

    After the operand is loaded, the "x", "y", "z", and "w" components of the
    result vector are selected by the first, second, third, and fourth matches
    of the <extSwizComp> pattern in the <extendedSwizzle> rule.

    A result component can be selected from any of the four components of the
    operand or the constants 0.0 and 1.0.  The result component can also be
    optionally negated.  The following pseudocode describes the component
    selection method.  "operand" refers to the vector operand, "select" is an
    enumerant where the values ZERO, ONE, X, Y, Z, and W correspond to the
    <extSwizSel> rule matching "0", "1", "x", "y", "z", and "w", respectively.
    "negate" is TRUE if and only if the <optionalSign> rule in <extSwizComp>
    matches "-".

      float ExtSwizComponent(floatVec operand, enum select, boolean negate)
      {
          float result;
          switch (select) {
            case ZERO:  result = 0.0; break;
            case ONE:   result = 1.0; break;
            case X:     result = operand.x; break;
            case Y:     result = operand.y; break;
            case Z:     result = operand.z; break;
            case W:     result = operand.w; break;
          }
          if (negate) {
            result = -result;
          }
          return result;
      }

    The entire extended swizzle operation is then defined using the following
    pseudocode:

      tmp = VectorLoad(op0);
      result.x = ExtSwizComponent(tmp, xSelect, xNegate);
      result.y = ExtSwizComponent(tmp, ySelect, yNegate);
      result.z = ExtSwizComponent(tmp, zSelect, zNegate);
      result.w = ExtSwizComponent(tmp, wSelect, wNegate);

    "xSelect", "xNegate", "ySelect", "yNegate", "zSelect", "zNegate",
    "wSelect", and "wNegate" correspond to the "select" and "negate" values
    above for the four <extSwizComp> matches.  

    Since this instruction allows for component selection and negation for
    each individual component, the grammar does not allow the use of the
    normal swizzle and negation operations allowed for vector operands in
    other instructions.


    Section 2.14.5.27,  XPD:  Cross Product

    The XPD instruction computes the cross product using the first three
    components of its two vector operands to generate the x, y, and z
    components of the result vector.  The w component of the result vector is
    undefined.

      tmp0 = VectorLoad(op0);
      tmp1 = VectorLoad(op1);
      result.x = tmp0.y * tmp1.z - tmp0.z * tmp1.y;
      result.y = tmp0.z * tmp1.x - tmp0.x * tmp1.z;
      result.z = tmp0.x * tmp1.y - tmp0.y * tmp1.x;


    Section 2.14.6,  Program Matrices

    In addition to GL's conventional matrices, several additional program
    matrices are available for use as program parameters.  These matrices have
    names of the form MATRIX<i>_ARB where <i> is between zero and <n>-1 where
    <n> is the value of the implementation-dependent constant
    MAX_PROGRAM_MATRICES_ARB.  The MATRIX<i>_ARB constants obey MATRIX<i>_ARB
    = MATRIX0_ARB + <i>.  The value of MAX_PROGRAM_MATRICES_ARB must be at
    least eight.  The maximum stack depth for program matrices is defined by
    the MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB and must be at least 1.


    Section 2.14.7  Required Vertex Program State 

    The state required to support program objects of all targets consists of:

      an integer for the program error position, initially -1;

      an array of ubytes for the program error string, initially empty;

      and the state that must be maintained to indicate which integers are
      currently in use as program object names.

    The state required to support the vertex program target consists of:

      a bit indicating whether or not program mode is enabled, initially
      disabled;

      a bit indicating whether or not vertex program two-sided color mode is
      enabled, initially disabled;

      a bit indicating whether or not vertex program point size mode is
      enabled, initially disabled;

      a set of MAX_PROGRAM_ENV_PARAMETERS_ARB four-component floating-point
      program environment parameters, initially set to (0,0,0,0);

      and an unsigned integer naming the currently bound vertex program,
      initially zero.

   The state required for each vertex program object consists of:

      an unsigned integer indicating the program object name;

      an array of type ubyte containing the program string, initially empty;

      an unsigned integer holding the length of the program string, initially
      zero;

      an enum indicating the program string format, initially
      PROGRAM_FORMAT_ASCII_ARB;

      five unsigned integers holding the number of instruction, temporary
      variable, vertex attribute binding, address register, and program
      parameter binding resources used by the program, initially all zero;

      five unsigned integers holding the number of native instruction,
      temporary variable, vertex attribute binding, address register, and
      program parameter binding resources used by the program, initially all
      zero;

      and a set of MAX_PROGRAM_LOCAL_PARAMETERS_ARB four-component
      floating-point program local parameters, initially set to (0,0,0,0).

   Initially, no vertex program objects exist.


Additions to Chapter 3 of the OpenGL 1.3 Specification (Rasterization) 

    Modify Section 3.3, Points (p. 63)

    (replace the first paragraph) When vertex program mode and vertex progam
    point size mode are both enabled, the point size used for point
    rasterization is taken from the transformed vertex's point size attribute.
    Otherwise, it is controlled with

     void PointSize(float size);

    size specifies the width or diameter of a point.  The initial point size
    value is 1.0.  A value less than or equal to zero results in the error
    INVALID_VALUE.

    Vertex program point size mode is enabled and disabled by calling Enable
    or Disable with the symbolic value VERTEX_PROGRAM_POINT_SIZE_ARB.


    Modify Section 3.9, Color Sum (p. 154)

    After texturing, a fragment has two RGBA colors: a primary color c_pri
    (which texturing, if enabled, may have modified) and a secondary color
    c_sec.  If color sum is enabled, the R, G, and B components of these two
    colors are summed, and with the A component of the primary color produce a
    single post-texturing RGBA color c. The components of c are then clamped
    to the range [0,1].  If color sum is disabled, then c_pri is assigned to
    the post-texturing color.

    Color sum is enabled or disabled using the generic Enable and Disable
    commands, respectively, with the symbolic constant COLOR_SUM_ARB.  If
    vertex program mode is disabled and lighting is enabled, the color sum
    stage is always applied, ignoring the value of COLOR_SUM_ARB.

    The state required is a single bit indicating whether color sum is enabled
    or disabled. In the initial state, color sum is disabled.


    Modify Section 3.10, Fog (p. 154)

    (modify second paragraph) This factor f may be computed according to one
    of three equations:

            f = exp(-d*c),                               (3.24)
            f = exp(-(d*c)^2), or                        (3.25)
            f = (e-c)/(e-s)                              (3.26)

    If vertex program mode is enabled or if the fog source (as defined below)
    is FOG_COORDINATE_EXT, then c is the fragment's fog coordinate.
    Otherwise, the c is the eye-coordinate distance from the eye, (0,0,0,1) in
    eye-coordinates, to the fragment center. ...

Additions to Chapter 4 of the OpenGL 1.3 Specification (Per-Fragment
Operations and the Framebuffer) 

    None

Additions to Chapter 5 of the OpenGL 1.3 Specification (Special Functions) 

    Modify Section 5.1, Evaluators (p. 181)

    (modify next-to-last paragraph, p. 184) For MAP VERTEX 3, let q = p. For
    MAP VERTEX 4, let q=(x/w,y/w,z/w), where (x; y; z;w) = p. Then let 

            dq   dq
        m = -- x --.
            du   dv

    The the generated analytic normal, n, is given by n=m if vertex program
    mode is enabled or by n=m/|m| if vertex program mode is disabled.


    Modify Section 5.4, Display Lists (p. 191)

    (modify third paragraph, p. 195) ... These are IsList, GenLists, ...,
    IsProgramARB, GenProgramsARB, DeleteProgramsARB, and
    VertexAttribPointerARB, EnableVertexAttribArrayARB,
    DisableVertexAttribArrayARB, as well as IsEnabled and all the Get commands
    (chapter 6).


Additions to Chapter 6 of the OpenGL 1.3 Specification (State and State
Requests)

    Modify Section 6.1.2, Data Conversions (p. 198)

    (add before last paragraph, p. 198) The matrix selected by the current
    matrix mode can be queried by calling GetBooleanv, GetIntegerv, GetFloatv,
    and GetDoublev with <pname> set to CURRENT_MATRIX_ARB; the matrix will be
    returned in transposed form with <pname> set to
    TRANSPOSE_CURRENT_MATRIX_ARB.  The depth of the selected matrix stack can
    be queried with <pname> set to CURRENT_MATRIX_STACK_DEPTH_ARB.  Querying
    CURRENT_MATRIX_ARB and CURRENT_MATRIX_STACK_DEPTH_ARB is the only means
    for querying the matrix and matrix stack depth of the program matrices
    described in section 2.14.6.


    Modify Section 6.1.11, Pointer and String Queries (p. 206)

    (modify last paragraph, p. 206) ... The possible values for <name> are
    VENDOR, RENDERER, VERSION, EXTENSIONS, and PROGRAM_ERROR_STRING_ARB.

    (add after last paragraph of section, p. 207) Queries of
    PROGRAM_ERROR_STRING_ARB return a pointer to an implementation-dependent
    program load error string.  If the last call to ProgramStringARB failed to
    load a program, the returned string describes at least one reason why the
    program failed to load.  If the last call to ProgramStringARB successfully
    loaded a program, the returned string may be empty (containing only a zero
    terminator) or may contain one or more implementation-dependent warning
    messages.  The contents of the error string are guaranteed to remain
    constant only until the next ProgramStringARB command, which may overwrite
    the error string.


    Insert a new Section 6.1.12, Program Queries (p. 207), between existing
    sections 6.1.11 and 6.1.12.

    Section 6.1.12, Program Queries

    The commands

      void GetProgramEnvParameterdvARB(enum target, uint index,
                                       double *params);
      void GetProgramEnvParameterfvARB(enum target, uint index,
                                       float *params);

    obtain the current value for the program environment parameter numbered
    <index> for the given program target <target>, and places the information
    in the array <params>.  The error INVALID_ENUM is generated if <target>
    specifies a nonexistent program target or a program target that does not
    support program environment parameters.  The error INVALID_VALUE is
    generated if <index> is greater than or equal to the
    implementation-dependent number of supported program environment
    parameters for the program target.

    When <target> is VERTEX_PROGRAM_ARB, each program parameter returned is an
    array of four values.

    The commands

      void GetProgramLocalParameterdvARB(enum target, uint index,
                                         double *params);
      void GetProgramLocalParameterfvARB(enum target, uint index,
                                         float *params);

    obtain the current value for the program local parameter numbered <index>
    belonging to the program object currently bound to <target>, and places
    the information in the array <params>.  The error INVALID_ENUM is
    generated if <target> specifies a nonexistent program target or a program
    target that does not support program local parameters.  The error
    INVALID_VALUE is generated if <index> is greater than or equal to the
    implementation-dependent number of supported program local parameters for
    the program target.

    When the program target type is VERTEX_PROGRAM_ARB, each program
    local parameter returned is an array of four values.

    The command

      void GetProgramivARB(enum target, enum pname, int *params);

    obtains program state for the program target <target>, writing the state
    into the array given by <params>.  GetProgramivARB can be used to
    determine the properties of the currently bound program object or
    implementation limits for <target>.

    If <pname> is PROGRAM_LENGTH_ARB, PROGRAM_FORMAT_ARB, or
    PROGRAM_BINDING_ARB, GetProgramivARB returns one integer holding the
    program string length (in bytes), program string format, and program name,
    respectively, for the program object currently bound to <target>.

    If <pname> is MAX_PROGRAM_LOCAL_PARAMETERS_ARB or
    MAX_PROGRAM_ENV_PARAMETERS_ARB, GetProgramivARB returns one integer
    holding the maximum number of program local parameters or program
    environment parameters, respectively, supported for the program target
    <target>.

    If <pname> is MAX_PROGRAM_INSTRUCTIONS_ARB, MAX_PROGRAM_TEMPORARIES_ARB,
    MAX_PROGRAM_PARAMETERS_ARB, MAX_PROGRAM_ATTRIBS_ARB, or
    MAX_PROGRAM_ADDRESS_REGISTERS_ARB, GetProgramivARB returns a single
    integer giving the maximum number of instructions, temporaries,
    parameters, attributes, and address registers that can be used by a
    program of type <target>.  If <pname> is PROGRAM_INSTRUCTIONS_ARB,
    PROGRAM_TEMPORARIES_ARB, PROGRAM_PARAMETERS_ARB, PROGRAM_ATTRIBS_ARB, or
    PROGRAM_ADDRESS_REGISTERS_ARB, GetProgramivARB returns a single integer
    giving the number of instructions, temporaries, parameters, attributes,
    and address registers used by the current program for <target>.

    If <pname> is MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB,
    MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, MAX_PROGRAM_NATIVE_PARAMETERS_ARB,
    MAX_PROGRAM_NATIVE_ATTRIBS_ARB, or
    MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB, GetProgramivARB returns a single
    integer giving the maximum number of native instruction, temporary,
    parameter, attribute, and address register resources available to a
    program of type <target>.  If <pname> is PROGRAM_NATIVE_INSTRUCTIONS_ARB,
    PROGRAM_NATIVE_TEMPORARIES_ARB, PROGRAM_NATIVE_PARAMETERS_ARB,
    PROGRAM_NATIVE_ATTRIBS_ARB, or PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB,
    GetProgramivARB returns a single integer giving the number of native
    instruction, temporary, parameter, attribute, and address register
    resources consumed by the program currently bound to <target>.  Native
    resource counts will reflect the results of implementation-dependent
    scheduling and optimization algorithms applied by the GL, as well as
    emulation of non-native features.  If <pname> is
    PROGRAM_UNDER_NATIVE_LIMITS_ARB, GetProgramivARB returns 0 if the native
    resource consumption of the program currently bound to <target> exceeds
    the number of available resources for any resource type, and 1 otherwise.

    The command

      void GetProgramStringARB(enum target, enum pname, void *string);

    obtains the program string for the program object bound to <target> and
    places the information in the array <string>.  <pname> must be
    PROGRAM_STRING_ARB.  <n> ubytes are returned into the array program where
    <n> is the length of the program in ubytes, as returned by GetProgramivARB
    when <pname> is PROGRAM_LENGTH_ARB.  The program string is always returned
    using the format given when the program string was specified.

    The commands

      void GetVertexAttribdvARB(uint index, enum pname, double *params);
      void GetVertexAttribfvARB(uint index, enum pname, float *params);
      void GetVertexAttribivARB(uint index, enum pname, int *params);

    obtain the vertex attribute state named by <pname> for the vertex
    attribute numbered <index> and places the information in the array
    <params>.  <pname> must be one of VERTEX_ATTRIB_ARRAY_ENABLED_ARB,
    VERTEX_ATTRIB_ARRAY_SIZE_ARB, VERTEX_ATTRIB_ARRAY_STRIDE_ARB,
    VERTEX_ATTRIB_ARRAY_TYPE_ARB, VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB, or
    CURRENT_VERTEX_ATTRIB_ARB.  Note that all the queries except
    CURRENT_VERTEX_ATTRIB_ARB return client state.  The error INVALID_VALUE is
    generated if <index> is greater than or equal to MAX_VERTEX_ATTRIBS_ARB.
    The error INVALID_OPERATION is generated if <index> is zero and <pname> is
    CURRENT_VERTEX_ATTRIB_ARB, as there is no current value for vertex
    attribute zero.

    The command

      void GetVertexAttribPointervARB(uint index, enum pname, void **pointer);
    
    obtains the pointer named <pname> for vertex attribute numbered <index>
    and places the information in the array <pointer>.  <pname> must be
    VERTEX_ATTRIB_ARRAY_POINTER_ARB.  The INVALID_VALUE error is generated if
    <index> is greater than or equal to MAX_VERTEX_ATTRIBS_ARB.

    The command

      boolean IsProgramARB(uint program);

    returns TRUE if <program> is the name of a program object.  If <program>
    is zero or is a non-zero value that is not the name of a program object,
    or if an error condition occurs, IsProgramARB returns FALSE.  A name
    returned by GenProgramsARB, but not yet bound, is not the name of a
    program object.


    Concerning Section 6.1.12, Saving and Restoring State (p. 207):

    (no actual modifications to the spec) Only the enables, current vertex
    attributes, and vertex array state introduced by this extension can be
    pushed and popped.  See the attribute column in Table X.6 for determining
    what vertex program state can be pushed and popped with PushAttrib,
    PopAttrib, PushClientAttrib, and PopClientAttrib.


Additions to Appendix A of the OpenGL 1.3 Specification (Invariance)

    Add to end of Section A.3 (p. 242):

      Rule 4.  Vertex program instructions not relevant to the calculation of
      any result must have no effect on that result.

      Rule 5.  Vertex program instructions relevant to the calculation of any
      result must always produce the identical result.

    Instructions relevant to the calculation of a result are any instructions
    in a sequence of instructions that eventually determine the source values
    for the calculation under consideration.

    There is no guaranteed invariance between vertices transformed by
    conventional GL vertex transform mode and vertices transformed by vertex
    program mode.  Multi-pass rendering algorithms that require rendering
    invariances to operate correctly should not mix conventional GL vertex
    transform mode with vertex program mode for different rendering passes,
    except by using the position invariance option (section 2.14.4.5.1) in all
    vertex program mode passes.  However, such algorithms will operate
    correctly if the algorithms limit themselves to a single mode of vertex
    transformation.


Additions to the AGL/GLX/WGL Specifications

    Program objects are shared between AGL/GLX/WGL rendering contexts if
    and only if the rendering contexts share display lists.  No change
    is made to the AGL/GLX/WGL API.

    Changes to program objects shared between multiple rendering contexts will
    be serialized (i.e., the changes will occur in a specific order).  

    Changes to a program object made by one rendering context are not
    guaranteed to take effect in another rendering context until the other
    calls BindProgram to bind the program object.  

    When a program object is deleted by one rendering context, the object
    itself is not destroyed until it is no longer the current program object
    in any context.  However, the name of the deleted object is removed from
    the program object name space, so the next attempt to bind a program using
    the same name will create a new program object.  Recall that destroying a
    program object bound in the current rendering context effectively unbinds
    the object being destroyed.


Dependencies on EXT_vertex_weighting and ARB_vertex_blend

    If EXT_vertex_weighting and ARB_vertex_blend are both not supported, all
    discussions of vertex weights should be removed.  

    In particular, references to vertex weights should be removed from Table
    X.1, and the description of ArrayElement in section 2.8.  The line

      "weight" <vtxOptWeightNum>

    should be removed from the <vtxAttribItem> grammar rule, and the grammar
    rules <vtxOptWeightNum> and <vtxWeightNum> should be deleted.
    "vertex.weight" and "vertex.weight[n]" should be removed from Table X.2.
    The discussion of vertex weights in section 2.14.3.1 should be removed.

    Additionally, the first line of Table X.3.8 should be modified to read:

      Binding                               Underlying State
      ------------------------------------  ---------------------------
        state.matrix.modelview              modelview matrix
    

Dependencies on ARB_matrix_palette:

    If ARB_matrix_palette is not supported, all discussions of per-vertex
    matrix indices and the matrix palette should be removed.

    In particular, the reference to matrix indices should be removed from the
    description of ArrayElement in section 2.8.  The line

      "matrixindex" "[" <vtxWeightNum> "]"

    should be removed from the <vtxAttribItem> grammar rule.  The line

      "palette" "[" <statePaletteMatNum> "]"

    should be removed from the <stateMatrixName> grammar rule, and the
    <statePaletteMatNum> grammar rule should be removed entirely.
    "vertex.matrixindex[n]" should be removed from Table X.2, and
    "state.matrix.palette[n]" should be removed from Table X.3.8.  The
    discussion of vertex matrix indices in section 2.14.3.1 should be removed.

Dependencies on EXT_point_parameters and ARB_point_parameters

    The discussion of point size determination in EXT/ARB_point_parameters
    should qualified to indicate that this functionality only applies when
    vertex program mode is disabled.

    If EXT/ARB_point_parameters is not supported, references to point
    parameter state should be eliminated.  In particular,

      "attenuation"

    should be eliminated from the <statePointProperty> grammar rule, and the
    corresponding entries in Table X.3.7 should be eliminated.

    Additionally, references to the minimum and maximum point sizes and the
    fade threshold should be removed from Table X.3.7 and the explanatory text
    immediately thereafter.  The components column of the "state.point.size"
    binding in Table X.3.7 should read (s,0,0,1).

    Even if EXT/ARB_point_parameters is not supported, the point size result
    (result.pointsize) still operates as specified.

Dependencies on EXT_fog_coord

    If EXT_fog_coord is not supported, references to fog coordinates should be
    removed from Table X.1, and the description of ArrayElement in section
    2.8.  The line "fogcoord" should be removed from the <vtxAttribItem>
    grammar rule, and "vertex.fogcoord" should be removed from Table X.2.
    Also, the use of FOG_COORDINATE_SOURCE_EXT in section 3.10 should be
    removed.

    Even if EXT_fog_coord is not supported, the fog coordinate output
    (result.fogcoord) still operates as specified.  When in vertex program
    mode, there are no well-defined eye coordinates that could be used for
    fog.  This means that the functionality of EXT_fog_coord is required to
    implement ARB_vertex_program even if the EXT_fog_coord extension itself is
    not supported.

Dependencies on EXT_secondary_color

    If EXT_secondary_color is not supported, references to secondary color
    should be removed from Table X.1, and the description of ArrayElement in
    section 2.8.  The line "secondary" should be removed from the
    <vtxOptColorType> grammar rule, and "vertex.color.secondary" should be
    removed from Table X.2.

    Even if EXT_secondary_color is not supported, the secondary color results
    (result.color.secondary, result.color.front.secondary,
    result.color.back.secondary) still operate as specified in program mode,
    and when in program mode, the color sum enable behaves exactly as
    specified in EXT_secondary_color.  These vertex result registers are
    required to implement OpenGL 1.2's separate specular mode within a vertex
    program.

    The color sum enable enumerant from EXT_secondary_color has been brought
    over and renamed to COLOR_SUM_ARB.  The enumerant value itself is
    unchanged from EXT_secondary_color.

Dependencies on ARB_transpose_matrix

    If ARB_transpose_matrix is not supported, the discussion of
    TRANSPOSE_CURRENT_MATRIX_ARB in the edits to section 6.1.2 should be
    removed.

Interactions with NV_vertex_program

    The existing NV_vertex_program extension, if supported, also provides a
    similar vertex programming model.  This extension is incompatible with
    NV_vertex_program in a number of different ways.  Mixing the two models in
    a single application is possible but not recommended.  The interactions
    between the extensions are defined below.

    Functions, enumerants, and programs defined in NV_vertex_program are
    called "NV functions", "NV enumerants", and "NV programs" respectively.
    Functions, enumerants, and programs defined in ARB_vertex_program are
    called "ARB functions", "ARB enumerants", and "ARB programs" respectively.

    The following enumerants are identical in the two extensions:

      ARB_vertex_program                  NV_vertex_program
      ------------------------------      ------------------------------
      VERTEX_PROGRAM_ARB                  VERTEX_PROGRAM_NV
      VERTEX_PROGRAM_POINT_SIZE_ARB       VERTEX_PROGRAM_POINT_SIZE_NV
      VERTEX_PROGRAM_TWO_SIDE_ARB         VERTEX_PROGRAM_TWO_SIDE_NV
      VERTEX_ATTRIB_ARRAY_SIZE_ARB        ATTRIB_ARRAY_SIZE_NV
      VERTEX_ATTRIB_ARRAY_STRIDE_ARB      ATTRIB_ARRAY_STRIDE_NV
      VERTEX_ATTRIB_ARRAY_TYPE_ARB        ATTRIB_ARRAY_TYPE_NV
      CURRENT_VERTEX_ATTRIB_ARB           CURRENT_ATTRIB_NV
      VERTEX_ATTRIB_ARRAY_POINTER_ARB     ATTRIB_ARRAY_POINTER_NV
      PROGRAM_LENGTH_ARB                  PROGRAM_LENGTH_NV
      PROGRAM_STRING_ARB                  PROGRAM_STRING_NV
      PROGRAM_ERROR_POSITION_ARB          PROGRAM_ERROR_POSITION_NV
      CURRENT_MATRIX_ARB                  CURRENT_MATRIX_NV
      CURRENT_MATRIX_STACK_DEPTH_ARB      CURRENT_MATRIX_STACK_DEPTH_NV
      MAX_PROGRAM_MATRICES_ARB            MAX_TRACK_MATRICES_NV
      MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB  MAX_TRACK_MATRIX_STACK_DEPTH_NV
        
    The following GL state is identical in the two extensions and can be set
    or queried using either NV functions or ARB functions.

      - Vertex program mode enable.

      - Vertex program point size mode enable.

      - Vertex program two sided mode enable.

      - Program error position.

      - NV_vertex_program "program parameters" and ARB_vertex_program "program
        environment parameters".

      - Current values of generic vertex attributes.  Conventional and generic
        vertex attributes will alias according to the NV_vertex_program spec,
        which is permissible but optional under ARB_vertex_program.

      - NV_vertex_program "tracking matrices" and ARB_vertex_program "program
        matrices".  The NV and ARB enumerants passed to MatrixMode are
        different, however.

      - Vertex attribute array sizes, types, strides, and pointers.

      - Vertex program object names, targets, formats, program string, program
        string lengths, and residency information.  The ARB and NV query
        functions operate differently.  The ARB query function does not allow
        queries of target (passed in to the query) and residency information.
        The NV query function does not allow queries of program name (passed
        in to the query) or format.  The format of NV programs is always
        PROGRAM_FORMAT_ASCII_ARB.

      - Current matrix and current matrix stack depth.

      - Implementation-dependent limits on number of tracking/program matrices
        and tracking/program matrix stack depth.

      - Program object name space.  Program objects are created differently in
        the NV and ARB specs.  Under the NV spec, program objects are created
        by calling LoadProgramNV.  Under the ARB spec, program objects are
        created by calling BindProgramARB with an unused program name.
       
    The following state is provided only by ARB_vertex_program:

      - Program error string.  Querying the error string after calling
        LoadProgramNV produces undefined results.

      - Vertex attribute array normalization enables.  Setting up vertex
        attribute arrays through NV functions will set the normalization
        enable appropriately based on the NV spec.

      - Vertex program object resource counts and native resource counts.
        These values are undefined for NV programs.

      - Vertex program local parameters.  They can not be used by NV programs.

      - Implementation-dependent limits on the number of program environment
        parameters, program local parameters, resource counts, and native
        resource counts.  These limits are baked into the NV spec, except for
        native counts, which don't exist.

    The following state is provided only by NV_vertex_program:

      - TrackMatrix enables and transforms.

      - Generic vertex attribute evaluator maps.  The NV evaluator
        functionality will be supported even for ARB programs.

    The following are additional functional differences between
    ARB_vertex_program and NV_vertex_program:

      - ARB program temporaries, address registers, and result registers are
        initially undefined.  The corresponding values in NV programs are
        initialized to (0,0,0,0), 0, and (0,0,0,1), respectively.  ARB
        programs running on NV_vertex_program platforms can not rely on
        NV_vertex_program initialization behavior for temporaries or address
        registers, but result registers will be initialized to (0,0,0,1).  In
        any event, ARB programs that rely on NV_vertex_program initialization
        may not behave properly on other platforms that support
        ARB_vertex_program but not NV_vertex_program.

      - NV programs use a set of fixed variable and register names, with no
        support for user-defined variables.  ARB programs provide no support
        for fixed variable names; all variables must be declared, explicitly
        or implicitly, in the program.

      - ARB programs support parameter variables that can be bound to selected
        GL state variables, and are updated automatically when the underlying
        state changes.  NV programs provide no such support; applications must
        set program parameters themselves.

      - ARB programs allow program constants to be declared in the program
        text; NV programs require that constants be loaded into the program
        parameter array.

      - ARB programs support program local parameters; NV programs do not.
        Applications using multiple NV programs must manage the shared program
        parameter array appropriately.

      - ARB_vertex_program vertex array support provides a normalized flag to
        optionally normalize fixed-point array data to the [0,1] or [-1,1]
        range.  ARB_vertex_program also provides several immediate-mode entry
        points with the same support.  NV_vertex_program supports normalized
        data only for unsigned byte data types, and does not support
        non-normalized unsigned bytes.  VertexAttrib4ub{v}NV was renamed to
        VertexAttrib4Nub{v}ARB to indicate that the 4ub call normalizes its
        parameters to a [0,1] range.

      - ARB_vertex_blend and ARB_matrix_palette support are documented by the
        ARB spec, but not by the NV spec.

      - ARB_vertex_program contains an OPTION mechanism for future
        extensibility, and a position invariant program option.  Both features
        are found in NV_vertex_program1_1, but not in NV_vertex_program.

      - NV_vertex_program supports a vertex state program target that allows
        programs to write to program parameters (VERTEX_STATE_PROGRAM_NV).  No
        such support exists in ARB_vertex_program.  Running a NV state program
        will update the program parameter/program environment parameter array,
        and such updates can be visible through ARB programs.

      - LoadProgramNV entry point was changed to ProgramStringARB to match
        OpenGL convention that a verb should not be included in a command name
        that merely sets state.

      - The formal parameter name for program objects was "id" in
        NV_vertex_program; in ARB_vertex_program, this formal name is now
        "program" to match how texture object routines name their formal
        texture object names "texture".

      - NV_vertex_program has language that makes it sound that LoadProgramNV
        (ProgramStringARB) only accepts the VERTEX_PROGRAM_NV target and the
        start token must be "!!VP1.0".  This extension clarifies the language
        so that it is clear that other targets and start token types are
        permitted.

      - NV_vertex_program numeric requirements are not present in the ARB
        spec.  The ARB spec requires nothing more than the numeric
        requirements spelled out in section 2.1.1 (Floating-Point
        Computations) in the core specification.

      - ARB programs allow single instructions to source multiple distinct
        vertex attributes or program parameters.  NV programs do not.  On
        current NV_vertex_program hardware, such instructions may require
        additional instructions and temporaries to execute.

      - ARB programs support the folowing instructions not supported by NV
        "VP1.0" programs:

            * ABS:  absolute value.  Supported on VP1.1 NV programs, but not
              on VP1.0 programs.  Equivalent to "MAX dst, src, -src".

            * EX2:  exponential base 2.  On VP1.0 and VP1.1 hardware, this
              instruction will be emulated using EXP and a number of
              additional instructions.

            * FLR:  floor.  On VP1.0 and VP1.1 hardware, this instruction will
              be emulated using an EXP and an ADD instruction.

            * FRC:  fraction.  On VP1.0 and VP1.1 hardware, this instruction
              will be emulated using an EXP instruction, and possibly a MOV
              instruction to replicate the scalar result.

            * LG2:  logarithm base 2.  On VP1.0 and VP1.1 hardware, this
              instruction will be emulated using LOG and a number of
              additional instructions.

            * POW:  exponentiation.  On VP1.0 and VP1.1 hardware, this
              instruction will be emulated using LOG, MUL, and EXP
              instructions, and possibly additional instructions to generate a
              high-precision result.

            * SUB:  subtraction.  Supported on VP1.1 NV programs, but not on
              VP1.0 programs.  Equivalent to "ADD dst, src1, -src2".

            * SWZ:  extended swizzle.  On VP1.0 and VP1.1 hardware, this
              instruction will be emulated using a single MAD instruction and
              a program parameter constant.

            * XPD:  cross product.  On VP1.0 and VP1.1 hardware, this
              instruction will be emulated using a MUL and a MAD instruction.

      - The COLOR_SUM_EXT enable is ignored when NV programs are executed
        (default secondary color outputs are zero) but not when ARB programs
        are executed (default secondary color outputs are undefined).  The
        driver will take care of the color sum operation based on which type
        of program is currently bound.

      - NV programs are required to write a vertex position; ARB programs are
        not.

      - There is both an ARB and an NV boolean enable for each generic
        array (two booleans per generic array).  Each generic array's NV
        enable is enabled with EnableClientState(VERTEX_ATTRIB_ARRAYn_NV)
        or disabled with DisableClientState(VERTEX_ATTRIB_ARRAYn_NV)
        while each generic array's ARB enable is enabled
        with EnableVertexAttribArrayARB(n) and disabled with
        DisableVertexAttribArrayARB(n).

        Enabling (or disabling) an ARB generic array enables (or disables)
        BOTH the NV and ARB generic array booleans.

        However enabling (or disabling) the NV generic array enable
        changes only the NV generic array enable (the ARB enable is
        UNchanged).

        When an enabled valid current vertex program (whether specified
        as an ARB or NV vertex program) is bound, the NV generic array
        enables are considered (and the ARB enables are ignored).  If a
        given NV generic array enable is true, the corresponding generic
        array state is applied.  However if there is an enabled valid
        vertex program and a particular NV generic array is disabled, then
        the corresponding conventional aliased array state is applied.

        When the current vertex program is disabled or not valid (so
        conventional vertex processing is performed), the ARB generic
        array enables are considered (and the NV enables are ignored).
        If a given ARB generic array enable is true, the corresponding
        generic array state is applied.  However if the current vertex
        program is disabled or NOT valid and a particular ARB generic
        array is disabled, then the corresponding conventional aliased
        array state is applied.

        This behavior means generic vertex arrays can be applied to
        conventional vertex processing when the ARB generic vertex array
        enable boolean is true.  For example, you can send normalized
        UNSIGNED_SHORT texture coordinate set arrays as aliased generic
        vertex arrays where conventionally UNSIGNED_SHORT texture
        coordinate set arrays are unnormalized.

    NV_vertex_program interaction Issues:

      - Should matrix tracking support extend to ARB program environment
        parameters?


Interactions with EXT_vertex_shader

    The existing EXT_vertex_shader extension, if supported, also provides a
    similar vertex programming model. This extension is incompatible with
    ARB_vertex_program in a number of different ways.  Mixing the two models
    in a single application is possible but not recommended. The interactions
    between the extensions are defined below.

    First, it should be trivially noted that an EXT_vertex_shader "shader"
    serves the same purpose as an ARB_vertex_program "program".  The two terms
    will be used interchangeably throughout this discussion.

    The most obvious difference between the two extensions is that the
    definition of the vertex program is accomplished in EXT_vertex_shader
    through the use of instruction-specifying procedure calls and is
    accomplished in ARB_vertex_program by providing a textual string
    describing the program. This is mostly a distinction of interface rather
    than functionality.

    Each extension provides its own distinct set of GL state, entry points,
    and enumerants. However, there are several areas of overlap both in
    conceptual framework and in programming model that are worth noting for
    those familiar with both API's.

    1. Resource terminology and types

       Both ARB_vertex_program and EXT_vertex_shader offer access to similar
       types of resources for use by vertex programs.

       The following terms describe roughly equivalent resources in their
       respective extensions:

       EXT_vertex_shader   ARB_vertex_program                    Note
       -----------------   ------------------                    ----
       instructions        instructions
       variants            attributes
       locals              temporaries
       local constants     parameters bound to inline constants  (a)
       invariants          parameters bound to GL state and      (b)
                           program environment parameters

         a. ARB_vertex_program has no intrinsic storage type that corresponds
            to EXT_vertex_shader's LOCAL_CONSTANT storage type, but rather
            supports program parameters bound to inline constant vectors
            specified within the program text. This essentially makes
            LOCAL_CONSTANT a special case of an ARB_vertex_program program
            parameter. The values of these inline constant parameters can not
            be changed without redefining the program itself, just like the
            values of EXT_vertex_shader LOCAL_CONSTANTs.

         b. ARB_vertex_program has no intrinsic storage type that corresponds
            to EXT_vertex_shader's INVARIANT storage type, but rather supports
            program parameters bound to GL state variables, program
            environment parameters, and program local parameters. This
            essentially makes INVARIANT a special case of an
            ARB_vertex_program program parameter. The values of these bound
            program parameters can be changed without redefining the program
            itself, but remain constant from vertex to vertex during vertex
            program execution, just like the values of EXT_vertex_shader
            INVARIANTs.

       ARB_vertex_program also adds the concept of a program local parameter,
       which has no direct analogue in EXT_vertex_shader, as it represents a
       parameter that is stored locally with the program object, but the
       values of these parameters can be changed without redefining the
       program itself.

    2. Resource usage queries

       Both ARB_vertex_program and EXT_vertex_shader provide queries to assist
       in determining the resource usage of a given shader and whether the
       shader would "fit" within the limits imposed by the underlying hardware
       implementation. The application can investigate the maximum numbers of
       shader resources supported by an implementation, shader resources
       available in hardware, and resources consumed by a given shader after
       being compiled into the implementation's native representation.

       In EXT_vertex_shader (see the end of section 2.14 of the
       EXT_vertex_shader specification), the queries are handled by glGet.

       In ARB_vertex_programs (see section 2.14.3.7 of this specification),
       similar queries are handled by GetProgramivARB, with a target of
       VERTEX_PROGRAM_ARB.

       The following queries exist in both extensions and serve roughly
       equivalent purposes in each:

       EXT_vertex_shader                             ARB_vertex_program
       -----------------                             ------------------
       MAX_VERTEX_SHADER_INSTRUCTIONS_EXT            MAX_PROGRAM_INSTRUCTIONS_ARB
       MAX_VERTEX_SHADER_VARIANTS_EXT                MAX_PROGRAM_ATTRIBS_ARB
       MAX_VERTEX_SHADER_LOCALS_EXT                  MAX_PROGRAM_TEMPORARIES_ARB

       MAX_OPTIMIZED_VERTEX_SHADER_INSTRUCTIONS_EXT  MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB
       MAX_OPTIMIZED_VERTEX_SHADER_VARIANTS_EXT      MAX_PROGRAM_NATIVE_ATTRIBS_ARB
       MAX_OPTIMIZED_VERTEX_SHADER_LOCALS_EXT        MAX_PROGRAM_NATIVE_TEMPORARIES_ARB

       VERTEX_SHADER_INSTRUCTIONS_EXT                PROGRAM_NATIVE_INSTRUCTIONS_ARB
       VERTEX_SHADER_VARIANTS_EXT                    PROGRAM_NATIVE_ATTRIBS_ARB
       VERTEX_SHADER_LOCALS_EXT                      PROGRAM_NATIVE_TEMPORARIES_ARB

       VERTEX_SHADER_OPTIMIZED_EXT                   PROGRAM_UNDER_NATIVE_LIMITS_ARB

       ARB_vertex_program offers additional queries to account for differences
       in some of the resource definitions (program environment parameters and
       program local parameters, address registers, etc.) as well as the
       ability to separately query a compiled program's resource usage
       according to the specification versus a possibly more efficient
       resource usage obtained by passing the program through by a "smart"
       compiler.

       The following queries do not exist in ARB_vertex_program due to the
       slightly different resource models:

       EXT_vertex_shader                                    ARB_vertex_program
       -----------------                                    ------------------
       {MAX_}{OPTIMIZED_}VERTEX_SHADER_INVARIANTS_EXT       (a)
       {MAX_}{OPTIMIZED_}VERTEX_SHADER_LOCAL_CONSTANTS_EXT  (a)

         a. ARB_vertex_program coalesces all of the different program
            parameters (environment, local, inline constant, and those bound
            to GL state) into a single queryable resource for
            PROGRAM_PARAMETERS.  EXT_vertex_shader provides separate queries
            even though these parameters may consume the same resource on some
            implementations.

       The following queries do not exist in EXT_vertex_shader due to the
       slightly different resource models:

       EXT_vertex_shader    ARB_vertex_program
       -----------------    ------------------
       (b)                  PROGRAM_*_ARB

       (c)                  {MAX_}{NATIVE_}PROGRAM_PARAMETERS_ARB

       (d)                  {MAX_}{NATIVE_}PROGRAM_ADDRESS_REGISTERS_ARB

         b. These queries are used to find out how many resources a given
            program used according to the specification, *before* running the
            program through an optimizing compiler.  This distinction is not
            made in EXT_vertex_shader.

         c. These queries are used to find out how many parameters were used
            by a program or are allowed by an implementation, in total without
            distinguishing between environment parameters, program local
            parameters, inline constant parameters, or parameters bound to GL
            state.  EXT_vertex_shader does not provide this information.

         d. EXT_vertex_shader does not provide have any address register
            resources since all dynamic array references are handled with the
            atomic OP_INDEX instruction.

    3. Symbols and variable names

       In EXT_vertex_shader resources that represent storage locations
       (i.e. INVARIANTS, VARIANTS, LOCALS, LOCAL_CONSTANTS) are abstractly
       referenced through a GL-allocated symbol id obtained from
       GenSymbolsEXT. This level of abstraction is provided to allow the
       implementation to make hardware-dependent decisions about the best way
       to arrange, allocate, and re-use hardware resources.

       Though ARB_vertex_program does not use symbol id's to refer to similar
       types of resources, it does provide similar functionality by allowing a
       vertex program to declare arbitrarily named variables for each resource
       in use. These names are assigned using the declaration syntax
       associated with the "PARAM", "ATTRIB", "TEMP", and "OUTPUT", and
       "ADDRESS" keywords.

    4. Program management

       With the exception of the actual program specification itself,
       EXT_vertex_shader and ARB_vertex_program have very similar program
       management API's.

       The following procedures serve roughly equivalent functions in their
       respective extensions.

       EXT_vertex_shader            ARB_vertex_program
       -----------------            ------------------
       BindVertexShaderEXT          BindProgramARB
       GenVertexShadersEXT          GenProgramsARB
       DeleteVertexShaderEXT        DeleteProgramsARB
       
       The following procedures are used in EXT_vertex_shader to define the
       program instruction sequence, and are not present in ARB_vertex_program
       since the string provided to ProgramStringARB fully defines the program
       contents.
       
           ShaderOp1EXT
           ShaderOp2EXT
           ShaderOp3EXT
           SwizzleEXT
           WriteMaskEXT
           InsertComponentEXT
           ExtractComponentEXT

    5. Data specification routines

       With the exception of the discrepancies in data types and resource
       names described above, EXT_vertex_shader and ARB_vertex_program provide
       similar program data specification and "current data query" API's.

       The following procedures serve roughly equivalent functions in their
       respective extensions:

       EXT_vertex_shader            ARB_vertex_program           Note
       -----------------            ------------------           -----
       SetInvariantEXT              ProgramEnvParameter4*ARB     (a)
       GetInvariant*vEXT            GetProgramEnvParameter*vARB  (a)
       Variant*vEXT                 VertexAttrib*ARB
       VariantPointerEXT            VertexAttribPointerARB
       GetVariant*vEXT              GetVertexAttrib*vARB
       GetVariantPointervEXT        GetVertexAttribPointervARB
       EnableVariantClientStateEXT  EnableVertexAttribArrayARB
       DisableVariantClientStateEXT DisableVertexAttribArrayARB
       IsVariantEnabledEXT          GetVertexAttrib*vARB         (b)

         a. See item #1 and #2 for more information on the relationship
            between EXT_vertex_shader invariants and ARB_vertex_program
            program parameters.

         b. The enabled state of an attribute array in ARB_vertex_program can
            be queried with GetVertexAttrib*v and a parameter of
            VERTEX_ATTRIB_ARRAY_ENABLED_ARB. In EXT_vertex_shader there is a
            dedicated enabled query procedure.

       However, there are some data specification routines in
       EXT_vertex_shader that have no procedure call analogue in
       ARB_vertex_program as their functions are subsumed by the string
       representation of the program itself.

       The following procedures in EXT_vertex_shader have functionality
       roughly covered by the following strings within the program text in
       ARB_vertex_shader:

       EXT_vertex_shader            ARB_vertex_program           Note
       -----------------            ------------------           -----
       SetLocalConstantEXT          PARAM C = {<x>,<y>,<z>,<w>};  (c)

       BindLightParameterEXT        state.light[n].*
       BindMaterialParameterEXT     state.material.*              (d)
       BindTexGenParameterEXT       state.texgen[n].*

       BindTextureUnitParameterEXT
         CURRENT_TEXTURE_COORDS     vertex.texcoord[n]
         TEXTURE_MATRIX             state.matrix.texture[n]

       BindParameterEXT
         CURRENT_VERTEX_EXT         vertex.position
         CURRENT_NORMAL             vertex.normal
         CURRENT_COLOR              vertex.color.*
         MODELVIEW_MATRIX           state.matrix.modelview[n]
         PROJECTION_MATRIX          state.matrix.projection
         MVP_MATRIX_EXT             state.matrix.mvp
         COLOR_MATRIX               <unavailable>                 (e)
         CLIP_PLANE                 state.clip[n].plane
         FOG_COLOR                  state.fog.color
         FOG_DENSITY                state.fog.params.x
         FOG_START                  state.fog.params.y
         FOG_END                    state.fog.params.z
         LIGHT_MODEL_AMBIENT        state.lightmodel.ambient

         c. Note that while EXT_vertex_shader style local constants can be
            specified using inline constants in the program text, there is no
            functionality in ARB_vertex_program that corresponds to the
            GetLocalConstant*vEXT call. That is, program parameters bound to
            inline constant vectors can be set in the text, but not queried
            from the application.

         d. Note that while EXT_vertex_shader supports binding material
            properties to variants, ARB_vertex_shader only supports binding
            them to program parameters (invariants). See item #11 below for
            more information.

         e. Note that while EXT_vertex_shader supports binding color matrix if
            the ARB_imaging subset is supported, ARB_vertex_shader does not
            allow for such a binding. See item #11 below for more information.

    6. Data types

       EXT_vertex_shader supports data types of SCALAR, VECTOR, and MATRIX.

       ARB_vertex_program intrinsically supports only vectors, though it
       allows for the definition of a matrix as a contiguous allocation of
       four row vectors. Some operations that, in EXT_vertex_shader require
       scalar inputs or scalar outputs, will, in ARB_vertex_program, use the
       selected component of the source vector as input and/or replicate their
       output to all components.

       Further, EXT_vertex_shader supports a pair of InsertComponents and
       ExtractComponents functions that are not available (nor required) in
       ARB_vertex_program, as they essentially provide for conversion between
       the SCALAR, VECTOR, and MATRIX data types.

    7. Input swizzles and output write-masks

       In EXT_vertex_shader, write masks are specified as a type of
       "instruction", using WriteMaskEXT, while in ARB_vertex_program, write
       masks are specified as modifiers to the destination resource with
       writemask modifiers, such as ".xyz" or ".w".

       In EXT_vertex_shader, source operand swizzles (component re- ordering,
       negation, and hard-coding to the value 0 and +/- 1.0) are also
       specified as a type of "instruction", using SwizzleEXT.

       In ARB_vertex_program, swizzles can either be handled as instruction
       ("SWZ") or as part of a modifier of the source argument to an
       instruction. The only differences between the two methods is that the
       source modifiers in ARB_vertex_program do not provide the ability to
       use 0.0 and +/- 1.0, or negate individual components, while the "SWZ"
       instruction does.

   8. Support for clipping and user clip planes

      Both extensions provide similar support for traditional clipping to the
      view frustum, namely that frustum clipping is not subsumed by vertex
      shader, or vertex program execution.

      Additionally, EXT_vertex_shader supports user clip planes by
      transforming the user clip planes from eye-space into clip space and
      clipping in the clip space coordinate system. This is supported as long
      as the projection matrix is non-singular.

      ARB_vertex_program provides similar functionality but only for programs
      specified using the "position invariant" option. For more information on
      user clip-plane support, see issue #20 and section 2.14.4.5.1 of this
      specification.

   9. Support for glRasterPos

      EXT_vertex_shader does not support transforming the current raster
      position vertex by the current vertex shader, while ARB_vertex_program
      does.

  10. Relative addressing.

      The string based syntax of ARB_vertex_program supports a relative
      addressing model where a given declared array can be dynamically
      dereferenced by first loading a declared ADDRESS register, using the
      "ARL" instruction with a value obtained at program execution then using
      that named ADDRESS register as the index to dereference a declared array
      of parameters later on.  See section 2.14.3.5 of this specification for
      details.

      For example, in ARB_vertex_program you can specify the following
      piece of a program.

          PARAM arr[5]  = { program.env[0..4] };
          ADDRESS addr;
          ATTRIB v1 = vertex.attrib[1];
          ARL addr, v1;
          MOV result, arr[addr.x + 1];

      EXT_vertex_shader supports relative addressing as as a single atomic
      operation through the use of the instruction OP_INDEX_EXT, as in

          ShaderOp2EXT(OP_INDEX_EXT, <res>, <arg1>, <arg2>).

      OP_INDEX_EXT supports relative addressing by taking the value stored in
      the register referred to by <arg1> and adding that value to the register
      number referred to by <arg2>, and loading <res> with the value stored in
      the register at the resulting offset.  EXT_vertex_shader has the
      requirement that the register referred to by <arg2> is allocated as one
      of a contiguous range of symbols obtained from a single call to
      GenSymbolsEXT.

      To achieve the same functionality as the above ARB_vertex_program, using
      EXT_vertex_shader, one could allocate a LOCAL symbol to hold a "fake"
      address register, and do a similar type of dynamic dereference
      operation, placing the output in a temporary LOCAL before giving it as
      an source argument to the "real" instruction.

       arr_contiguousArraySymbol =
            GenSymbolsEXT(GL_VECTOR_EXT, GL_LOCAL_EXT, GL_FULL_RANGE_EXT, 5);

       addr_fakeAddressRegSymbol =
            GenSymbolsEXT(GL_VECTOR_EXT, GL_LOCAL_EXT, GL_FULL_RANGE_EXT, 1);

       v1_srcSymbolForARLOp =
            GenSymbolsEXT(GL_VECTOR_EXT, GL_VARIANT_EXT, GL_FULL_RANGE_EXT, 1);

       temp =
            GenSymbolsEXT(GL_VECTOR_EXT, GL_LOCAL_EXT, GL_FULL_RANGE_EXT, 1);

       result_ForMovOpSymbol =
            GenSymbolsEXT(GL_VECTOR_EXT, GL_LOCAL_EXT, GL_FULL_RANGE_EXT, 1);

        // load fake ADDRESS register
        ExtractComponentEXT(
            addr_fakeAddressRegSymbol,
            v1_srcSymbolForARLOp,
            0);

        // do dynamic dereference into a temp
        ShaderOp2EXT(
            GL_OP_INDEX_EXT,
            temp,
            addr_fakeAddressRegSymbol,
            contiguousArraySymbol);

        // do operation we really wanted (MOV) using looked up src value
        ShaderOp1EXT(
            GL_OP_MOV_EXT,
            result_ForMovOpSymbol,
            temp,
            (arr_contiguousArraySymbol + 1));

   11. Available GL state bindings

       Both EXT_vertex_shader and ARB_vertex_program offer the ability to bind
       program resources to pieces of OpenGL state so that the values of
       OpenGL state parameters are available to the program without the
       application having to copy the state values manually into program
       parameters.

       The two extensions differ in exactly which pieces of state are
       available to a vertex program, with the main difference being that
       ARB_vertex_program offers a more comprehensive set of state bindings.

       First, EXT_vertex_shader can bind pieces of GL state considered to be
       "scalar" values to a single SCALAR symbol, whereas ARB_vertex_program,
       which handles only vectors, packs up to 4 scalar bindings into a single
       vector parameter.

       Similarly, EXT_vertex_shader can bind pieces of GL state considered to
       be "matrix" values to a single MATRIX symbol, whereas
       ARB_vertex_program supports bindings to matrix data by using up to four
       vectors to store the rows of the matrix.

       Other differences between the state bindings available in both API's
       are listed below:

         a. In EXT_vertex_shader, the light attenuation factors (CONSTANT,
            LINEAR, QUADRATIC, and SPOT_EXPONENT), are available as separate
            SCALAR bindings.

            In ARB_vertex_program, the light attenuation factors are all
            packed into a single vector called state.light[n].attenuation with
            the CONSTANT, LINEAR, QUADRATIC, and SPOT_EXPONENT factors in the
            x,y,z, and w parameters respectively.

         b. In EXT_vertex_shader the spotlight direction (SPOT_DIRECTION) and
            spot light cutoff angle (SPOT_CUTOFF), are available as separate
            bindings.

            In ARB_vertex_program, these parameters are all packed into a
            single vector called state.light[n].spot.direction with the with
            the x,y,z parameters of the spotlight direction and the the
            *cosine* of the cutoff angle in the x,y,z, and w parameters
            respectively.

         c. In EXT_vertex_shader, the fog equation factors (FOG_DENSITY,
            FOG_START, FOG_END), are avaiable as separate SCALAR bindings.

            In ARB_vertex_program, the fog equation factors are all packed
            into a single vector called state.fog.params with the fog density,
            linear start, linear end, and pre-computed 1.0/ (end-start)
            factors in the x,y,z, and w parameters respectively.

         d. In EXT_vertex_shader, material properties can be bound to a
            variant (i.e. "attribute" in ARB_vertex_program terminology) and
            can change per vertex, and the changes take effect immediately.

            In ARB_vertex_program, material properties can only be bound to
            program parameters, and any changes to material properties between
            a Begin/End pair are not guaranteed to take effect until the
            following End command.

         e. In EXT_vertex_shader, the material shininess property is bound to
            a SCALAR variable.

            In ARB_vertex_program, the material shininess property is bound to
            a vector with elements { s, 0.0, 0.0, 1.0 } where "s" is the
            material shininess property.

         f. In EXT_vertex_shader, a program can bind to the current modelview,
            projection, composite modelview-projection, color, and texture
            matrices only in their entirety.

            In ARB_vertex_program, a program can bind to individual rows of
            any matrix, with the exception of the color matrix, which is not
            available in ARB_vertex_program.

            Additionally, ARB_vertex_program adds the ability to bind to
            multiple modelview matrices, multiple palette matrices, and a set
            of matrices dedicated for use with vertex programs called "program
            matrices". Further, ARB_vertex_program offers the ability to bind
            to the inverse, transpose, and inverse_transpose of any of the
            matrices available for binding.

            If an application desires the functionality of binding to the
            color matrix in ARB_vertex_program, that application can use one
            of the other matrices, for instance program matrices, to store the
            current color matrix.

   12. Instruction set differences.

       In general, ARB_vertex_program's instruction set is a super-set of the
       EXT_vertex_shader instructions that take VECTOR inputs and produce
       VECTOR outputs. The versions of the EXT_vertex_shader instructions that
       take non-vector (i.e. SCALAR or MATRIX) operands are almost all
       available in vector form as well.

       The instructions from each set correspond as follows:

       EXT_vertex_shader       ARB_vertex_program   Note
       -----------------       ------------------   -----
       OP_INDEX_EXT           <unavailable>         (a)
       OP_NEGATE_EXT          <unavailable>         (b)
       OP_DOT3_EXT             "DP3"                (c)
       OP_DOT4_EXT             "DP4"
       OP_MUL_EXT              "MUL"
       OP_ADD_EXT              "ADD"
       OP_MADD_EXT             "MAD"
       OP_FRAC_EXT             "FRC"
       OP_MAX_EXT              "MAX"
       OP_MIN_EXT              "MIN"
       OP_SET_GE_EXT           "SGE"
       OP_SET_LT_EXT           "SLT"
       OP_CLAMP_EXT           <unavailable>         (d)
       OP_FLOOR_EXT            "FLR"
       OP_ROUND_EXT           <unavailable>         (e)
       OP_EXP_BASE_2_EXT       "EX2"                (f)
       OP_LOG_BASE_2_EXT       "LG2"                (g)
       OP_POWER_EXT            "POW"                (h)
       OP_RECIP_EXT            "RCP"                (i)
       OP_RECIP_SQRT_EXT       "RSQ"                (j)
       OP_SUB_EXT              "SUB"
       OP_CROSS_PRODUCT_EXT    "XPD"                (k)
       OP_MULTIPLY_MATRIX_EXT <unavailable>         (l)
       OP_MOV_EXT              "MOV"
      <unavailable>            "ARL"                (a)
      <unavailable>            "ABS"
      <unavailable>            "LIT"
      <unavailable>            "EXP"                (f)
      <unavailable>            "LOG"                (g)
      <unavailable>            "DPH"
      <unavailable>            "DST"

       There are a few minor differences, however.

       a. EXT_vertex_shader's OP_INDEX_EXT is not available in
          ARB_vertex_program which uses the "ARL" instruction and array syntax
          to handle dynamically dereferencing source data. See item #10 above
          and the discussion of "ARL" in section 2.14.3.5.

       b. EXT_vertex_shader's OP_NEGATE_EXT is not available in
          ARB_vertex_program. ARB_vertex_program can support a "NEGATE"
          operation through the use of swizzle modifiers on source operands or
          the "SWZ" instruction.

            MOV tempA, -tempB;

          or

            SWZ tempA, -tempB, x,y,z,w;

       c. The "w" component of EXT_vertex_shader's OP_DOT3_EXT instruction is
          left unchanged.

          However, in ARB_vertex_program, the "w" component gets the same
          result as the "x", "y", and "z" components.

       d. EXT_vertex_shader's OP_CLAMP_EXT is not available in
          ARB_vertex_program. ARB_vertex_program can support a "CLAMP"
          operation by using a pair of "MAX" and "MIN" instructions as in:

            # CLAMP arg1 to be within [arg2, arg3]
            MAX temp,   arg1, arg2;
            MIN result, temp, arg3;

       e. EXT_vertex_shader's OP_ROUND_EXT is not available in
          ARB_vertex_program. ARB_vertex_program can support a "ROUND"
          operation by using a pair of "ADD" and "FLOOR" instructions as in:

            ADD   temp,   arg1, 0.5;
            FLOOR result, temp;

       f. EXT_vertex_shader's OP_EXP_BASE_2_EXT is designed to support high
          precision calculations of base-2 exponentiation.

          ARB_vertex_program's "EX2" is the equivalent function, however
          ARB_vertex_program also offers an "EXP" function that is designed to
          support a lower precision approximation of base-2 exponentiation
          that can be further refined through an iterative process.
          
          On some implementations, both "EX2" and "EXP" may be carried out
          with the same high precision at no cost relative to each other.  As
          such, if a vertex program is using "EXP" with the intent of
          iteratively refining the approximation by using several successive
          instructions it may be more efficient to use a single call to "EX2"
          and get the high precision with a single instruction.

          If on the other hand, a single approximation is good enough, there
          is no additional cost to using "EXP" on such implementations.

          Further note that in EXT_vertex_shader, OP_EXP_BASE_2_EXT is
          specified to take a scalar operand, whereas ARB_vertex_program's
          "EXP" and "EX2" instruction each take a vector operand, use the "x"
          component, and then write (partial) results to all components of a
          destination vector.

       g. EXT_vertex_shader's OP_LOG_BASE_2_EXT is designed to support high
          precision calculations of base-2 logarithms.

          ARB_vertex_program's "LG2" is the equivalent function, however
          ARB_vertex_program also offers an "LOG" function that is designed to
          support a lower precision approximation of base-2 logarithms that
          can be further refined through an iterative process.

          On some implementations, both "LG2" and "LOG" may be carried out
          with the same high precision at no cost relative to each other.  As
          such, if a vertex program is using "LOG" with the intent of
          iteratively refining the approximation by using several successive
          instructions it may be more efficient to use a single call to "LG2"
          and get the high precision with a single instruction.

          If on the other hand, a single approximation is good enough, there
          is no additional cost to using "LOG" on such implementations.

          Further note that in EXT_vertex_shader, OP_LOG_BASE_2_EXT is
          specified to take a scalar operand, whereas ARB_vertex_program's
          "LOG" and "LOG2" instruction each take a vector operand, use the "x"
          component, and then write (partial) results to all components of a
          destination vector.

       h. EXT_vertex_shader's OP_POWER_EXT is designed to support high
          precision calculations of the power function.

          ARB_vertex_program's "POW" is the equivalent function.

          Further note that in EXT_vertex_shader, OP_POWER_EXT is specified to
          take a scalar operand, whereas ARB_vertex_program's "POW"
          instruction takes a vector operand, uses the "x" component, and
          replicates the same result to all components of a destination
          vector.

       i. EXT_vertex_shader's OP_RECIP_EXT is specified to take a scalar
          operand, whereas ARB_vertex_program's "RCP" instruction takes a
          single component of a vector and replicates the same result to all
          components of the destination vector.

       j. EXT_vertex_shader's OP_RECIP_SQRT_EXT is specified to take a scalar
          operand, whereas ARB_vertex_program's "RSQ" instruction takes a
          single component of a vector and replicates the same result to all
          components of the destination vector.

       k. The "w" component of EXT_vertex_shader's OP_CROSS_PRODUCT_EXT
          instruction is forced to 1.0;

          However, in ARB_vertex_program, the "w" component is left undefined
          and "writes to the w component of the destination are treated as
          disabled, regardless of the write mask specified in the XPD
          instruction".

       l. EXT_vertex_shader's OP_MULTIPLY_MATRIX is not available in
          ARB_vertex_program. ARB_vertex_program can support a "MATRIX
          MULTIPLY" operation by using a series of "DP4" instructions as in:

            PARAM mat[4] = { state.matrix.modelview };
            DP4 result.x, vec, mat[0];
            DP4 result.y, vec, mat[1];
            DP4 result.z, vec, mat[2];
            DP4 result.w, vec, mat[3];

   13. Vertex provoking behavior

       EXT_vertex_shader does not provoke vertex shader execution when variant
       0 is specified (either using Variant*EXT, or variant
       arrays). Applications are required to use the conventional Vertex* or
       vertex arrays to provoke a vertex in both vertex shader mode and
       conventional mode.  Variant 0 is considered current state and is
       queryable.

       Conversely, ARB_vertex_program does provoke vertex program execution
       when attribute 0 is specified (either using VertexAttrib*vARB, or
       attribute arrays) in both vertex program mode and conventional mode.
       Attribute 0 is not considered current state and is not queryable.

       For implementations that support both extensions, this means that if
       ARB_vertex_program is disabled, and EXT_vertex_shader is enabled, then
       specifying ARB_vertex_program's attribute 0 will still provoke
       execution of the currently bound EXT_vertex_shader defined shader.

   14. Enabled state

       On implementations that support both EXT_vertex_shader, and
       ARB_vertex_program, priority is given to ARB_vertex_program. That is to
       say, if both are enabled, the implementation uses the program defined
       by ARB_vertex_program and does not execute the currently bound
       EXT_vertex_shader shader unless or until ARB_vertex_program is
       subsequently disabled. Needless to say, it is not expected that a given
       application will actually attempt to use both vertex program API's at
       once.


GLX Protocol

     The following rendering commands are sent to the server as part of a
     glXRender request:

        VertexAttrib1svARB
            2           12              rendering command length
            2           4189            rendering command opcode
            4           CARD32          index
            2           INT16           v[0]
            2                           unused

        VertexAttrib1fvARB
            2           12              rendering command length
            2           4193            rendering command opcode
            4           CARD32          index
            4           FLOAT32         v[0]

        VertexAttrib1dvARB
            2           16              rendering command length
            2           4197            rendering command opcode
            4           CARD32          index
            8           FLOAT64         v[0]

        VertexAttrib2svARB
            2           12              rendering command length
            2           4190            rendering command opcode
            4           CARD32          index
            2           INT16           v[0]
            2           INT16           v[1]

        VertexAttrib2fvARB
            2           16              rendering command length
            2           4194            rendering command opcode
            4           CARD32          index
            4           FLOAT32         v[0]
            4           FLOAT32         v[1]

        VertexAttrib2dvARB
            2           24              rendering command length
            2           4198            rendering command opcode
            4           CARD32          index
            8           FLOAT64         v[0]
            8           FLOAT64         v[1]

        VertexAttrib3svARB
            2           16              rendering command length
            2           4191            rendering command opcode
            4           CARD32          index
            2           INT16           v[0]
            2           INT16           v[1]
            2           INT16           v[2]
            2                           unused

        VertexAttrib3fvARB
            2           20              rendering command length
            2           4195            rendering command opcode
            4           CARD32          index
            4           FLOAT32         v[0]
            4           FLOAT32         v[1]
            4           FLOAT32         v[2]

        VertexAttrib3dvARB
            2           32              rendering command length
            2           4199            rendering command opcode
            4           CARD32          index
            8           FLOAT64         v[0]
            8           FLOAT64         v[1]
            8           FLOAT64         v[2]

        VertexAttrib4bvARB
            2           12              rendering command length
            2           4230            rendering command opcode
            4           CARD32          index
            1           INT8            v[0]
            1           INT8            v[1]
            1           INT8            v[2]
            1           INT8            v[3]

        VertexAttrib4svARB
            2           16              rendering command length
            2           4192            rendering command opcode
            4           CARD32          index
            2           INT16           v[0]
            2           INT16           v[1]
            2           INT16           v[2]
            2           INT16           v[3]

        VertexAttrib4ivARB
            2           24              rendering command length
            2           4231            rendering command opcode
            4           CARD32          index
            4           INT32           v[0]
            4           INT32           v[1]
            4           INT32           v[2]
            4           INT32           v[3]

        VertexAttrib4ubvARB
            2           12              rendering command length
            2           4232            rendering command opcode
            4           CARD32          index
            1           CARD8           v[0]
            1           CARD8           v[1]
            1           CARD8           v[2]
            1           CARD8           v[3]

        VertexAttrib4usvARB
            2           16              rendering command length
            2           4233            rendering command opcode
            4           CARD32          index
            2           CARD16          v[0]
            2           CARD16          v[1]
            2           CARD16          v[2]
            2           CARD16          v[3]

        VertexAttrib4uivARB
            2           24              rendering command length
            2           4234            rendering command opcode
            4           CARD32          index
            4           CARD32          v[0]
            4           CARD32          v[1]
            4           CARD32          v[2]
            4           CARD32          v[3]

        VertexAttrib4fvARB
            2           24              rendering command length
            2           4196            rendering command opcode
            4           CARD32          index
            4           FLOAT32         v[0]
            4           FLOAT32         v[1]
            4           FLOAT32         v[2]
            4           FLOAT32         v[3]

        VertexAttrib4dvARB
            2           40              rendering command length
            2           4200            rendering command opcode
            4           CARD32          index
            8           FLOAT64         v[0]
            8           FLOAT64         v[1]
            8           FLOAT64         v[2]
            8           FLOAT64         v[3]

        VertexAttrib4NbvARB
            2           12              rendering command length
            2           4235            rendering command opcode
            4           CARD32          index
            1           INT8            v[0]
            1           INT8            v[1]
            1           INT8            v[2]
            1           INT8            v[3]

        VertexAttrib4NsvARB
            2           16              rendering command length
            2           4236            rendering command opcode
            4           CARD32          index
            2           INT16           v[0]
            2           INT16           v[1]
            2           INT16           v[2]
            2           INT16           v[3]

        VertexAttrib4NivARB
            2           24              rendering command length
            2           4237            rendering command opcode
            4           CARD32          index
            4           INT32           v[0]
            4           INT32           v[1]
            4           INT32           v[2]
            4           INT32           v[3]

        VertexAttrib4NubvARB
            2           12              rendering command length
            2           4201            rendering command opcode
            4           CARD32          index
            1           CARD8           v[0]
            1           CARD8           v[1]
            1           CARD8           v[2]
            1           CARD8           v[3]

        VertexAttrib4NusvARB
            2           16              rendering command length
            2           4238            rendering command opcode
            4           CARD32          index
            2           CARD16          v[0]
            2           CARD16          v[1]
            2           CARD16          v[2]
            2           CARD16          v[3]

        VertexAttrib4NuivARB
            2           24              rendering command length
            2           4239            rendering command opcode
            4           CARD32          index
            4           CARD32          v[0]
            4           CARD32          v[1]
            4           CARD32          v[2]
            4           CARD32          v[3]

        BindProgramARB
            2           12              rendering command length
            2           4180            rendering command opcode
            4           ENUM            target
            4           CARD32          program

        ProgramEnvParameter4fvARB
            2           32              rendering command length
            2           4184            rendering command opcode
            4           ENUM            target
            4           CARD32          index
            4           FLOAT32         params[0]
            4           FLOAT32         params[1]
            4           FLOAT32         params[2]
            4           FLOAT32         params[3]

        ProgramEnvParameter4dvARB
            2           44              rendering command length
            2           4185            rendering command opcode
            4           ENUM            target
            4           CARD32          index
            8           FLOAT64         params[0]
            8           FLOAT64         params[1]
            8           FLOAT64         params[2]
            8           FLOAT64         params[3]

        ProgramLocalParameter4fvARB
            2           32              rendering command length
            2           4215            rendering command opcode
            4           ENUM            target
            4           CARD32          index
            4           FLOAT32         params[0]
            4           FLOAT32         params[1]
            4           FLOAT32         params[2]
            4           FLOAT32         params[3]

        ProgramLocalParameter4dvARB
            2           44              rendering command length
            2           4216            rendering command opcode
            4           ENUM            target
            4           CARD32          index
            8           FLOAT64         params[0]
            8           FLOAT64         params[1]
            8           FLOAT64         params[2]
            8           FLOAT64         params[3]

    The ProgramStringARB is potentially large, and hence can be sent in a
    glXRender or glXRenderLarge request.

        ProgramStringARB
            2           16+len+p        rendering command length
            2           4217            rendering command opcode
            4           ENUM            target
            4           ENUM            format
            4           sizei           len
            len         LISTofBYTE      program
            p                           unused, p=pad(len)

         If the command is encoded in a glxRenderLarge request, the command
         opcode and command length fields above are expanded to 4 bytes each:

            4           16+len+p        rendering command length
            4           4217            rendering command opcode

    VertexAttribPointerARB, EnableVertexAttribArrayARB, and
    DisableVertexAttribArrayARB are entirely client-side commands.

    The remaining commands are non-rendering commands.  These commands are
    sent separately (i.e., not as part of a glXRender or glXRenderLarge
    request), using the glXVendorPrivateWithReply request:

        DeleteProgramsARB
            1           CARD8           opcode (X assigned)
            1           17              GLX opcode (glXVendorPrivateWithReply)
            2           4+n             request length
            4           1294            vendor specific opcode
            4           GLX_CONTEXT_TAG context tag
            4           INT32           n
            n*4         LISTofCARD32    programs

        GenProgramsARB
            1           CARD8           opcode (X assigned)
            1           17              GLX opcode (glXVendorPrivateWithReply)
            2           4               request length
            4           1295            vendor specific opcode
            4           GLX_CONTEXT_TAG context tag
            4           INT32           n
          =>
            1           1               reply
            1                           unused
            2           CARD16          sequence number
            4           n               reply length
            24                          unused
            n*4         LISTofCARD322   programs

        GetProgramEnvParameterfvARB
            1           CARD8           opcode (X assigned)
            1           17              GLX opcode (glXVendorPrivateWithReply)
            2           6               request length
            4           1296            vendor specific opcode
            4           GLX_CONTEXT_TAG context tag
            4           ENUM            target
            4           CARD32          index
            4                           unused
          =>
            1           1               reply
            1                           unused
            2           CARD16          sequence number
            4           m               reply length, m=(n==1?0:n)
            4                           unused
            4           CARD32          n (number of parameter components)

            if (n=1) this follows:

            4           FLOAT32         params
            12                          unused

            otherwise this follows:

            16                          unused
            n*4         LISTofFLOAT32   params

        GetProgramEnvParameterdvARB
            1           CARD8           opcode (X assigned)
            1           17              GLX opcode (glXVendorPrivateWithReply)
            2           6               request length
            4           1297            vendor specific opcode
            4           GLX_CONTEXT_TAG context tag
            4           ENUM            target
            4           CARD32          index
            4                           unused
          =>
            1           1               reply
            1                           unused
            2           CARD16          sequence number
            4           m               reply length, m=(n==1?0:n*2)
            4                           unused
            4           CARD32          n (number of parameter components)

            if (n=1) this follows:

            8           FLOAT64         params
            8                           unused

            otherwise this follows:

            16                          unused
            n*8         LISTofFLOAT64   params

        GetProgramLocalParameterfvARB
            1           CARD8           opcode (X assigned)
            1           17              GLX opcode (glXVendorPrivateWithReply)
            2           6               request length
            4           1305            vendor specific opcode
            4           GLX_CONTEXT_TAG context tag
            4           ENUM            target
            4           CARD32          index
            4                           unused
          =>
            1           1               reply
            1                           unused
            2           CARD16          sequence number
            4           m               reply length, m=(n==1?0:n)
            4                           unused
            4           CARD32          n (number of parameter components)

            if (n=1) this follows:

            4           FLOAT32         params
            12                          unused

            otherwise this follows:

            16                          unused
            n*4         LISTofFLOAT32   params

        GetProgramLocalParameterdvARB
            1           CARD8           opcode (X assigned)
            1           17              GLX opcode (glXVendorPrivateWithReply)
            2           6               request length
            4           1306            vendor specific opcode
            4           GLX_CONTEXT_TAG context tag
            4           ENUM            target
            4           CARD32          index
            4                           unused
          =>
            1           1               reply
            1                           unused
            2           CARD16          sequence number
            4           m               reply length, m=(n==1?0:n*2)
            4                           unused
            4           CARD32          n (number of parameter components)

            if (n=1) this follows:

            8           FLOAT64         params
            8                           unused

            otherwise this follows:

            16                          unused
            n*8         LISTofFLOAT64   params

        GetProgramivARB
            1           CARD8           opcode (X assigned)
            1           17              GLX opcode (glXVendorPrivateWithReply)
            2           5               request length
            4           1307            vendor specific opcode
            4           GLX_CONTEXT_TAG context tag
            4           ENUM            target
            4           ENUM            pname
          =>
            1           1               reply
            1                           unused
            2           CARD16          sequence number
            4           m               reply length, m=(n==1?0:n)
            4                           unused
            4           CARD32          n

            if (n=1) this follows:

            4           INT32           params
            12                          unused

            otherwise this follows:

            16                          unused
            n*4         LISTofINT32     params

        GetProgramStringARB
            1           CARD8           opcode (X assigned)
            1           17              GLX opcode (glXVendorPrivateWithReply)
            2           5               request length
            4           1308            vendor specific opcode
            4           GLX_CONTEXT_TAG context tag
            4           ENUM            target
            4           ENUM            pname
          =>
            1           1               reply
            1                           unused
            2           CARD16          sequence number
            4           (n+p)/4         reply length
            4                           unused
            4           CARD32          n
            16                          unused
            n           STRING          program
            p                           unused, p=pad(n)

        Note that VERTEX_ATTRIB_ARRAY_ENABLED_ARB,
        VERTEX_ATTRIB_ARRAY_SIZE_ARB, VERTEX_ATTRIB_ARRAY_STRIDE_ARB,
        VERTEX_ATTRIB_ARRAY_TYPE_ARB, and VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB
        may be queried by GetVertexAttrib[dfi]ARB, but generate no protocol
        and return client-side state.

        GetVertexAttribdvARB
            1           CARD8           opcode (X assigned)
            1           17              GLX opcode (glXVendorPrivateWithReply)
            2           5               request length
            4           1301            vendor specific opcode
            4           GLX_CONTEXT_TAG context tag
            4           INT32           index
            4           ENUM            pname
          =>
            1           1               reply
            1                           unused
            2           CARD16          sequence number
            4           m               reply length, m=(n==1?0:n*2)
            4                           unused
            4           CARD32          n

            if (n=1) this follows:

            8           FLOAT64         params
            8                           unused

            otherwise this follows:

            16                          unused
            n*8         LISTofFLOAT64   params

        GetVertexAttribfvARB
            1           CARD8           opcode (X assigned)
            1           17              GLX opcode (glXVendorPrivateWithReply)
            2           5               request length
            4           1302            vendor specific opcode
            4           GLX_CONTEXT_TAG context tag
            4           INT32           index
            4           ENUM            pname
          =>
            1           1               reply
            1                           unused
            2           CARD16          sequence number
            4           m               reply length, m=(n==1?0:n)
            4                           unused
            4           CARD32          n

            if (n=1) this follows:

            4           FLOAT32         params
            12                          unused

            otherwise this follows:

            16                          unused
            n*4         LISTofFLOAT32   params

        GetVertexAttribivARB
            1           CARD8           opcode (X assigned)
            1           17              GLX opcode (glXVendorPrivateWithReply)
            2           5               request length
            4           1303            vendor specific opcode
            4           GLX_CONTEXT_TAG context tag
            4           INT32           index
            4           ENUM            pname
          =>
            1           1               reply
            1                           unused
            2           CARD16          sequence number
            4           m               reply length, m=(n==1?0:n)
            4                           unused
            4           CARD32          n

            if (n=1) this follows:

            4           INT32           params
            12                          unused

            otherwise this follows:

            16                          unused
            n*4         LISTofINT32     params

        IsProgramARB
            1           CARD8           opcode (X assigned)
            1           17              GLX opcode (glXVendorPrivateWithReply)
            2           4               request length
            4           1304            vendor specific opcode
            4           GLX_CONTEXT_TAG context tag
            4           INT32           n
          =>
            1           1               reply
            1                           unused
            2           CARD16          sequence number
            4           0               reply length
            4           BOOL32          return value
            20                          unused

     When transferring vertex attribute array elements, there may not be a
     protocol encoding that exactly matches the combination of combination of
     size, normalization enable, and data type in the array.  If no match
     protocol encoding exists, the encoding for the corresponding 4-component
     attribute is used.  v[1] and v[2] are set to zero if not specified in the
     vertex array.  If v[3] is not specified in the vertex array, it is set to
     0x7F, 0x7FFF, 0x7FFFFFFF, 0xFF, 0xFFFF, or 0xFFFFFFFF for the
     VertexAttrib4NbvARB, VertexAttrib4NsvARB, VertexAttrib4NivARB,
     VertexAttrib4NubvARB, VertexAttrib4NusvARB, and VertexAttrib4NuivARB
     protocol encodings, respectively.  v[3] is set to one if it is not
     specified in the vertex array for the the VertexAttrib4bvARB,
     VertexAttrib4svARB, VertexAttrib4ivARB, VertexAttrib4ubvARB,
     VertexAttrib4usvARB, and VertexAttrib4uivARB protocol encodings.


Errors 
 
    The error INVALID_VALUE is generated by any VertexAttrib*ARB or
    GetVertexAttrib*ARB command if <index> is greater than or equal to
    MAX_VERTEX_ATTRIBS_ARB.

    The error INVALID_VALUE is generated by VertexAttribPointerARB or
    GetVertexAttribPointervARB if <index> is greater than or equal to
    MAX_VERTEX_ATTRIBS_ARB.

    The error INVALID_VALUE is generated by VertexAttribPointerARB if <size>
    is not one of 1, 2, 3, or 4.

    The error INVALID_VALUE is generated by VertexAttribPointerARB if <stride>
    is negative.

    The error INVALID_VALUE is generated by EnableVertexAttribArrayARB or
    DisableVertexAttribArrayARB if <index> is greater than or equal to
    MAX_VERTEX_ATTRIBS_ARB.

    The error INVALID_OPERATION is generated by ProgramStringARB if the
    program string <string> is syntactically incorrect or violates any
    semantic restriction of the execution environment of the specified program
    target <target>.

    The error INVALID_OPERATION is generated by BindProgramARB if <program> is
    the name of a program whose target does not match <target>.

    The error INVALID_VALUE is generated by any ProgramEnvParameter*ARB or
    GetProgramEnvParameter*ARB command if <index> is greater than or equal to
    the value of MAX_PROGRAM_ENV_PARAMETERS_ARB corresponding to the program
    target <target>.

    The error INVALID_VALUE is generated by any ProgramLocalParameter*ARB or
    GetProgramLocalParameter*ARB command if <index> is greater than or equal
    to the value of MAX_PROGRAM_LOCAL_PARAMETERS_ARB corresponding to the
    program target <target>.

    The error INVALID_OPERATION is generated if Begin, RasterPos, or any
    command that performs an explicit Begin is called when vertex program mode
    is enabled and the currently bound vertex program object does not contain
    a valid vertex program.

    The error INVALID_OPERATION is generated by GetVertexAttrib*ARB if <index>
    is zero and <pname> is CURRENT_VERTEX_ATTRIB_ARB.


New State


Get Value                        Type    Get Command    Initial Value Description         Section       Attribute
-------------------------------  ------  -------------  ------------- ------------------  ------------  ------------
VERTEX_PROGRAM_ARB               B       IsEnabled      False         vertex program      2.10          enable
                                                                      enable
VERTEX_PROGRAM_POINT_SIZE_ARB    B       IsEnabled      False         program-specified   2.14.3.7      enable
                                                                      point size mode
VERTEX_PROGRAM_TWO_SIDE_ARB      B       IsEnabled      False         two-sided color     2.14.3.7      enable
                                                                      mode
-                                96+xR4  GetProgramEnv- (0,0,0,0)     program environment 2.14.1        -
                                         ParameterARB                 parameters
CURRENT_VERTEX_ATTRIB_ARB        16+xR4  GetVertex-     undefined     generic vertex      2.7           current
                                         AttribARB                    attributes
PROGRAM_ERROR_POSITION_ARB       Z       GetIntegerv    -1            last program error  2.14.1        -
                                                                      position
PROGRAM_ERROR_STRING_ARB         0+xub   GetString      ""            last program error  2.14.1        -
                                                                      string

Table X.6.  New Accessible State Introduced by ARB_vertex_program.


Get Value                        Type    Get Command    Initial Value Description         Section       Attribute
-------------------------------  ------  -------------  ------------- ------------------  ------------  ------------
VERTEX_ATTRIB_ARRAY_ENABLED_ARB  16+xB   GetVertex-     False         vertex attrib       2.8           vertex-array
                                         AttribARB                    array enable
VERTEX_ATTRIB_ARRAY_SIZE_ARB     16+xZ   GetVertex-     4             vertex attrib       2.8           vertex-array
                                         AttribARB                    array size
VERTEX_ATTRIB_ARRAY_STRIDE_ARB   16+xZ+  GetVertex-     0             vertex attrib       2.8           vertex-array
                                         AttribARB                    array stride
VERTEX_ATTRIB_ARRAY_TYPE_ARB     16+xZ4  GetVertex-     FLOAT         vertex attrib       2.8           vertex-array
                                         AttribARB                    array type
VERTEX_ATTRIB_ARRAY_             16+xB   GetVertex-     False         vertex attrib       2.8           vertex-array
    NORMALIZED_ARB                       AttribARB                    array normalized
VERTEX_ATTRIB_ARRAY_POINTER_ARB  16+xP   GetVertex-     NULL          vertex attrib       2.8           vertex-array
                                         AttribPointerARB             array pointer

Table X.7.  New Accessible Client State Introduced by ARB_vertex_program.


Get Value                        Type   Get Command          Initial Value    Description             Sec       Attrib
--------------------             -----  -------------------  ---------------  ----------------------  --------  ------
PROGRAM_BINDING_ARB              Z+     GetProgramivARB      object-specific  bound program name      6.1.12    -
PROGRAM_LENGTH_ARB               Z+     GetProgramivARB      0                bound program length    6.1.12    -
PROGRAM_FORMAT_ARB               Z1     GetProgramivARB      PROGRAM_FORMAT_  bound program format    6.1.12    -
                                                             ASCII_ARB
PROGRAM_STRING_ARB               ubxn   GetProgramStringARB  (empty)          bound program string    6.1.12    -
PROGRAM_INSTRUCTIONS_ARB         Z+     GetProgramivARB      0                bound program           6.1.12    -
                                                                              instructions
PROGRAM_TEMPORARIES_ARB          Z+     GetProgramivARB      0                bound program           6.1.12    -
                                                                              temporaries
PROGRAM_PARAMETERS_ARB           Z+     GetProgramivARB      0                bound program           6.1.12    -
                                                                              parameter bindings
PROGRAM_ATTRIBS_ARB              Z+     GetProgramivARB      0                bound program           6.1.12    -
                                                                              attribute bindings
PROGRAM_ADDRESS_REGISTERS_ARB    Z+     GetProgramivARB      0                bound program           6.1.12    -
                                                                              address registers
PROGRAM_NATIVE_INSTRUCTIONS_ARB  Z+     GetProgramivARB      0                bound program native    6.1.12    -
                                                                              instructions
PROGRAM_NATIVE_TEMPORARIES_ARB   Z+     GetProgramivARB      0                bound program native    6.1.12    -
                                                                              temporaries
PROGRAM_NATIVE_PARAMETERS_ARB    Z+     GetProgramivARB      0                bound program native    6.1.12    -
                                                                              parameter bindings
PROGRAM_NATIVE_ATTRIBS_ARB       Z+     GetProgramivARB      0                bound program native    6.1.12    -
                                                                              attribute bindings
PROGRAM_NATIVE_ADDRESS_          Z+     GetProgramivARB      0                bound program native    6.1.12    -
    REGISTERS_ARB                                                             address registers
PROGRAM_UNDER_NATIVE_LIMITS_ARB  B      GetProgramivARB      0                bound program under     6.1.12    -
                                                                              native resource limits
-                                96+xR4 GetProgramLocal-     (0,0,0,0)        bound program local     2.14.1    -
                                        ParameterARB                          parameter value

Table X.8.  Program Object State.  Program object queries return attributes of
the program object currently bound to the program target <target>.


Get Value    Type    Get Command   Initial Value  Description              Sec       Attribute
---------    ------  -----------   -------------  -----------------------  --------  ---------
-            12+xR4  -             undefined      temporary registers      2.14.3.6  -
-            8+xR4   -             undefined      vertex result registers  2.14.3.7  -
             1+xZ1   -             undefined      vertex program           2.14.3.8  -
                                                  address registers

Table X.9.  Vertex Program Per-vertex Execution State.  All per-vertex
execution state registers are uninitialized at the beginning of program
execution.


Get Value                          Type      Get Command      Initial Value  Description          Sec      Attribute
------------------------------     --------  --------------   -------------  -------------------  -------  ---------
CURRENT_MATRIX_ARB                 m*n*xM^4  GetFloatv        Identity       current matrix       6.1.2    -
CURRENT_MATRIX_STACK_DEPTH_ARB     m*Z+      GetIntegerv      1              current stack depth  6.1.2    -

Table X.10.  Current matrix state where m is the total number of matrices
including texture matrices and program matrices and n is the number of
matrices on each particular matrix stack.  Note that this state is aliased
with existing matrix state.


New Implementation Dependent State
                                                              Minimum
Get Value                            Type    Get Command      Value       Description             Sec           Attrib
-----------------------------------  ----    ---------------  ----------  --------------------    ------------  ------
MAX_PROGRAM_ENV_PARAMETERS_ARB       Z+      GetProgramivARB  96          maximum program         2.14.1        -
                                                                          env parameters
MAX_PROGRAM_LOCAL_PARAMETERS_ARB     Z+      GetProgramivARB  96          maximum program         2.14.1        -
                                                                          local parameters
MAX_PROGRAM_MATRICES_ARB             Z+      GetIntegerv      8 (not to   maximum number of       2.14.6        -
                                                              exceed 32)  program matrices
MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB   Z+      GetIntegerv      1           maximum program         2.14.6        -
                                                                          matrix stack depth
MAX_PROGRAM_INSTRUCTIONS_ARB         Z+      GetProgramivARB  128         maximum program         6.1.12        -
                                                                          instructions
MAX_PROGRAM_TEMPORARIES_ARB          Z+      GetProgramivARB  12          maximum program         6.1.12        -
                                                                          temporaries
MAX_PROGRAM_PARAMETERS_ARB           Z+      GetProgramivARB  96          maximum program         6.1.12        -
                                                                          parameter bindings
MAX_PROGRAM_ATTRIBS_ARB              Z+      GetProgramivARB  16          maximum program         6.1.12        -
                                                                          attribute bindings
MAX_PROGRAM_ADDRESS_REGISTERS_ARB    Z+      GetProgramivARB  1           maximum program         6.1.12        -
                                                                          address registers
MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB  Z+      GetProgramivARB  -           maximum program native  6.1.12        -
                                                                          instructions
MAX_PROGRAM_NATIVE_TEMPORARIES_ARB   Z+      GetProgramivARB  -           maximum program native  6.1.12        -
                                                                          temporaries
MAX_PROGRAM_NATIVE_PARAMETERS_ARB    Z+      GetProgramivARB  -           maximum program native  6.1.12        -
                                                                          parameter bindings
MAX_PROGRAM_NATIVE_ATTRIBS_ARB       Z+      GetProgramivARB  -           maximum program native  6.1.12        -
                                                                          attribute bindings
MAX_PROGRAM_NATIVE_ADDRESS_          Z+      GetProgramivARB  -           maximum program native  6.1.12        -
    REGISTERS_ARB                                                         address registers

Table X.11.  New Implementation-Dependent Values Introduced by
ARB_vertex_program.  Values queried by GetProgramivARB require a <pname> of
VERTEX_PROGRAM_ARB.


Revision History

    Rev.    Date    Author    Changes
    ----  --------  --------  --------------------------------------------
    46    07/25/07  mjk       Document how the ARB and NV generic arrays
                              interact.  This documents NVIDIA's
                              long-standing implemented behavior.

    45    09/27/04  pbrown    Fixed GLX protocol, removing the unused <pname>
                              parameters for GetProgram{Env,Local}Parameter
                              [df]vARB, leaving an unused CARD32 in its place.
                              This was an error when propogating
                              NV_vertex_program protocol, which did have a
                              <pname> parameter.

    44    09/12/03  pbrown    Fixed opcode table entry for "ARL" -- it takes a
                              scalar operand as specified in the grammar.

    43    08/17/03  pbrown    Fixed a couple minor typos (missing quotes)
                              in the grammar.

    42    05/01/03  pbrown    Clarified the handling of color sum; old text
                              suggested that COLOR_SUM controlled the
                              operation even when doing separate specular
                              lighting.

    41    04/18/03  pbrown    Add a couple overlooked contributors.

    40    03/03/03  pbrown    Fixed list of immediate-mode VertexAttrib
                              functions in Section 2.7 -- there are no
                              normalized float functions (e.g., 
                              VertexAttrib4Nfv).  Clarified issue (42)
                              describing how point size is handled in vertex
                              program mode.

    39    01/31/03  pbrown    Fixed minor bug in the description of vertex
                              array state kept by the GL -- normalization
                              flags were omitted from the text (but were in
                              the state tables).

    38    01/08/03  pbrown    Fixed bug where "state.matrix.mvp" was specified
                              incorrectly -- it should be P*M0 rather than
                              M0*P.

    37    12/23/02  pbrown    Fixed minor typos.  Fixed state table bug where 
                              CURRENT_VERTEX_ATTRIB_ARB was incorrectly called
                              CURRENT_ATTRIB_ARB.

    36    09/09/02  pbrown    Fixed incorrect example of matrix row bindings
                              (and transposition).  Small wording/typo fixes.

    35    08/27/02  pbrown    Fixed several minor typos.  Documented that a
                              program string should not include a null
                              terminator in its first <len> characters.  Fixed
                              dangling reference in <paramMultipleItem>
                              grammar rule.  Fix incorrect wording in
                              computation of state.light.half vector.
                              Documented that the inverse of a singular matrix
                              is undefined.  Clarified that native
                              instructions can include additions due to
                              emulation of features not supported natively.
                              Documented that LG2 produces undefined results
                              with zero or negative inputs.  Clarified that
                              POW may be a LOG/MUL/EXP sequence, but isn't
                              necessarily so.  Disallowed multiple modelview
                              matrix syntax if ARB_vertex_blend or
                              EXT_vertex_weighting is unsupported.  Fixed
                              state table query function for attribute array
                              enables.  Added missing state table entry for
                              PROGRAM_UNDER_NATIVE_LIMITS_ARB.

    34    07/19/02  pbrown    Fixed typo in ArrayElement pseudo-code.

    33    07/17/02  pbrown    Fixed bug in the <stateLModProperty> grammar
                              rule.  Fixed documentation to indicate that
                              Enable/DisableVertexAttribArray are not display
                              listable.

    31    07/15/02  pbrown    Fixed <SWZ_instruction> grammar rule to match
                              the spec language -- base operand negation
                              doesn't apply, since you can independently
                              negate components.  Modified "XPD" instruction
                              to eliminate the implicit masking of the "w"
                              component; slight efficiency gain for some SW
                              implementations.  Modified "scenecolor" binding
                              to pass the diffuse alpha instead of the ambient
                              alpha; the former is more useful.

    30    07/02/02  pbrown    Minor wording fixes.

    29    06/21/02  pbrown    Mostly minor bug fixes from reviewer feedback;
                              also added one new item approved at ARB meeting.

                              Additions:  Added a "lightmodel.*.scenecolor"
                              holding lit color containing the composite
                              lighting result ignoring individual lights --
                              i.e., from only emissive materials and the light
                              model.  Added GLX protocol.

                              Minor changes:  Numerous minor typo and wording
                              fixes.  Added missing vertex array types to
                              vertex array size/type/normalized table.  Added
                              missing description of ambient light model color
                              binding.  Removed several references to language
                              features long since deleted.  Documented that
                              POW is not necessarily implemented as
                              LOG/MUL/EXP.  Fixed a couple minor errata in the
                              EXT_vertex_shader interaction section.  Added a
                              list of reserved keywords.

    28    06/16/02  pbrown    Minor updates based on feedback given on
                              versions 26 and 27.

                              Additions:  Added section on EXT_vertex_shader
                              interaction, provided by ATI.

                              Minor changes:  Minor grammar and readability
                              fixes.  Fixed several incomplete definitions.
                              Removed "GL" and "gl" prefixes from several
                              enumerants and function names to match spec
                              conventions.  Clarified the precision issue on
                              EX2/LG2.  Added missing functions that take
                              VERTEX_PROGRAM_ARB.  Clarified component
                              normalization on vertex arrays.  Clarified
                              clipping section to note that user clipping is
                              done with position invariant programs.
                              Clarified the handling of program zero in
                              BindProgramARB.  Fixed a couple incorrect
                              grammar rules.  Fixed incorrect grammar
                              references in description of vertex program
                              parameter array accesses.  Documented that the
                              SWZ instruction doesn't take "normal" swizzle
                              and negation modifiers, since it already has
                              some.  Clarified some NV_vertex_program
                              interactions.

    27    06/07/02  pbrown    Minor update based on ARB_vertex_program sample
                              implementation work.

                              Changes:  Changed fog coordinate attribute and
                              result binding name to "fogcoord" (was "fog").
                              Rearranged grammar based on sample
                              implementation verification.  There might be a
                              minor fix or two stuck in there.

    26    06/04/02  pbrown    Spec checkpoint published on the working group
                              web site.  Resolves most of the remaining open
                              issues. 

                              Deletions:  Removed the ability to bind the
                              color matrix (from ARB_imaging).

                              Changes:  Resolved the handling of vertex
                              attribute zero (it always specifies a vertex, in
                              program mode or not).  Resolved the handling of
                              generic and conventional vertex attribute arrays
                              (they are always sent, although they also have
                              "undefined aliasing" behavior).  Default values
                              of generic attributes are undefined, to
                              accommodate aliasing and non-aliasing
                              implementations.  Added pseudocode to document
                              the processing of ArrayElement.  Moved program
                              object language into the vertex program section.
                              Renamed the fog coordinate attribute and result
                              binding to "fogcoord".  Added missing
                              documentation of the agreed-upon semantic
                              restriction that programs can't bind
                              conventional / generic attribute pairs that may
                              alias.  Added documentation of what happens when
                              multiple contexts share program objects
                              Disallowed queries of generic attribute zero.

                              Fixes:  Fixed prototype for VertexAttrib4Nub.  

                              Minor Changes:  Minor typo and language
                              fixes. Added guidelines for future
                              programmability extensions.  Added several
                              missing grammar rules.

    25    05/30/02  pbrown    Spec checkpoint published on the working group
                              web site.

                              Additions:  Add "DPH" (dot product homogeneous)
                              instruction.  Added the ability to query the
                              current matrix in transposed form.  Assigned
                              enumerant values for program matrices.  Added
                              the ability bind selected rows of a matrix.
                              Added ability to bind matrix palette matrices.

                              Changes:  Renamed PROGRAM_NAME_ARB to
                              PROGRAM_BINDING_ARB.  Specifying the number of
                              elements in parameter arrays is now optional,
                              but compilation will fail if the specified count
                              does not match.  Programs performing
                              out-of-bounds array accesses using absolute
                              addressing will now fail to load.  Allow "$" in
                              token names.

                              Minor changes:  Completed scrub of the issues
                              and error list.  Added new issues about reserved
                              keywords, identifier characters, and parsing of
                              floating-point constants in programs.
                              Miscellaneous typo fixes.  Updated the grammar
                              to include light products and half angles, moved
                              material properties from per-vertex to parameter
                              bindings, and a few other miscellaneous fixes.
                              Simplified the matrix binding table.  Modified
                              the color sum portion of the spec to explicitly
                              add R,G,B only.  Removed several incorrect
                              errors.  Fixed program object state table.

    24    05/21/02  pbrown    Spec checkpoint published on the working group
                              web site.

                              Deletions:  Removed the semantic requirement
                              that vertex programs write a vertex position,
                              per working group resolution.
                              
                              Minor changes:  Cleaned up cruft in a number of
                              issues; many more to go.  Added several issues.
                              Documented that VertexAttrib functions are
                              allowed inside Begin/End pairs.  Changed default
                              initialization values of generic attributes to
                              accommodate attribute aliasing.  Documented that
                              point sizes and fog coordinates computed by
                              vertex programs are clipped during primitive
                              clipping.  Documented that vertex program
                              behavior is undefined in color index mode.

    23    05/21/02  pbrown    Spec checkpoint.  More changes from working
                              group deliberations.

                              Additions:  Added vertex materials as allowed
                              program parameter bindings.  Allow programs to
                              use vertex attribute binding names, program
                              parameter binding names, result variable binding
                              names, and constants in executable statements,
                              resulting in implicit bindings.  Added support
                              for binding a single row of a matrix.  Added
                              support for binding precomputed light/material
                              products.  Added restriction that a single GL
                              state vector can't be bound multiple times in
                              two separate arrays accessed with relative
                              addressing.  Added new section documenting the
                              various resource limits, and introducting the
                              idea of "native" resource limits and counts.

                              Deletions:  Removed vertex materials as allowed
                              vertex attribute bindings.

                              Minor changes:  Added more names to the
                              contributors list.  Updated issues concerning
                              undefined aliasing.  Moved NV_vertex_program
                              related issues to the NV_vertex_program
                              interaction sections.  Updated NV_vertex_program
                              interactions.  Updated lighting example using
                              new derived state bindings.  Clarified that
                              "!!ARBvp1.0" is not a token in the grammar and
                              that programs are parsed beginning immediately
                              after the header string.  Added text to explain
                              all attribute, program parameter, and result
                              bindings instead of depending on binding table
                              interpretations.  Broke the large program
                              parameter binding table into several smaller
                              tables, organized by function.  Documented that
                              the queryable program error string may contain
                              warnings when a program loads successfully, and
                              that a queried program error string is
                              guaranteed to remain constant only until the
                              next program load attempt.  Added PROGRAM_NAME
                              query to the appropriate state table.

    22    05/20/02  pbrown    Spec checkpoint.  More changes from working
                              group deliberations. 

                              Added functionality:  Assigned enumerant values.
                              Added "undefined (vertex attribute) aliasing"
                              language, where setting a generic attribute
                              leaves a conventional one undefined, and vice
                              versa.  Added support for matrix indices from
                              ARB_matrix_palette.  Added default program
                              object zero.  Added support for simple named
                              variable aliasing.  Added queries of API-level
                              and "native" resources used by a program and
                              their corresponding limits.  Added general query
                              to determine if a program fits in native limits.

                              Removed functionality:  Removed extension string
                              entry for position-invariant programs (now
                              mandatory).

                              Modified functionality:  GetProgram and
                              GetProgramString now take a target instead of a
                              program name.  Default values for 3 generic
                              attributes are changed for consistent aliasing.
                              Added 1/(end-start) binding for fog parameters.
                              Added precomputed infinite light/viewer half
                              angle binding.  ProgramString takes a "void *"
                              instead of a "ubyte *".

                              Minor Changes:  Clarified key terms for the
                              extension.  Documented that user clipping is not
                              supported in the base extension.  Added warnings
                              on a couple pitfalls from uninitalized result
                              registers.  Document that EXT_vertex_weighting
                              and ARB_vertex_blend use the same weight.
                              Cleaned up bindings for 4-component colors for
                              cases where only three components are used.
                              Documented the implicit absolute value operation
                              on the LOG instruction.  Renamed query token for
                              querying generic vertex attribute array enables.
                              Renamed and relocated vertex program binding
                              query.  Added language to Section 2.6.  Changed
                              syntax to bind a range of the environment or
                              local paramater array to use double dots ("..").
                              Clarified what happens on a weight binding using
                              more weights than an implementation supports.
                              Clarified the component selection pseudocode for
                              scalar operand loads.  Clarified what happens to
                              vertex program results during primitive
                              assembly.  Fixed a number of errors in the state
                              tables.

    21    04/29/02  pbrown    More changes from working group deliberations.

                              Added functionality:  Added "FLR", "FRC", "POW",
                              and "XPD" (cross product) instructions.  Added
                              functions to enable/disable generic attribute
                              arrays.  Added query of a program error string.
                              Added "format" enum argument to ProgramStringARB
                              to provide for possible programs not using ASCII
                              text.  Added new enums to permit different
                              limits for overall numbers of program
                              environment and local parameters and the number
                              of parameters that can be bound by a program.

                              Removed functionality:  Removed support for
                              evaluators for generic attributes.  Removed
                              support for program residency management.
                              Removed support for user clipping in standard
                              vertex programs.  Removed functionality to set
                              more than one program environment parameter at
                              once.

                              Issues/Changes:  Resolved set of immediate mode
                              VertexAttrib functions.  Combined parameter
                              bindings for several groups of related GL state.
                              Resolved user clipping issue by disallowing
                              except for position invariant programs.
                              Resolved limits for array relative offsets.
                              GenProgramsARB and DeleteProgramsARB will use
                              texture object model.  Program environment
                              parameters will not be pushed/popped.

                              Bug fixes:  Fixed vertex attribute index
                              prototypes (should be uint instead of int).
                              Fixed tokens used to query generic attribute
                              state (should have VERTEX prefixes).  Fixed
                              documentation of the alpha component of material
                              colors.  Fixed documentation of initial state
                              for vertex program objects.

                              Temporarily removed dated GLX protocol language
                              (will restore in one pass after resolving
                              remaining issues).

    20    04/17/02  pbrown    Clarify the meaning of individual components of
                              program parameters where the component mapping
                              is not obvious from the mapping table.
                              
    18    04/15/02  pbrown    Update spec to reflect issues resolved by the
                              working group on 4/11.

                              Started using "program matrix" terminology --
                              was "tracking matrix".  

                              Address register variables must now be declared.
                              The number of address registers can be queried.
                              Only 1-component address registers are currently
                              supported.  

                              VertexAttribPointer takes a separate argument to
                              indicate normalized data, now called
                              "normalized" (was "normalize").  

                              ProgramString and functions to set and query
                              local parameters all take a <target> and refer
                              to the currently bound program (previously took
                              a program number).  Have not touched other
                              somewhat related issues (e.g., is there a
                              program object zero?).
                              
                              Added COLOR_SUM enable (taken directly from
                              EXT_secondary_color) for completeness and a
                              few updates to EXT_secondary_color
                              interactions.
                              
                              Fixed cut-and-paste error in specification of
                              the clip-space user clip dot product.
                              
                              Documented special-case arithmetic for ADD, MAD,
                              and MUL.

                              Eliminated some wordiness in DP3 and DP4
                              instruction pseudo-code.

                              Minor changes not from working group:  More
                              verbose documentation on the user clipping
                              issue.  More detail on other opcode candidates.
                              Removed redundant color material issue.  Minor
                              fixes to error roundup (not complete) and to
                              state tables to reflect that most program
                              execution variables are initially undefined.

    17    04/08/02  pbrown    Issues:  Enumerated other candidates for
                              consideration in the instruction set -- there
                              may be more that I missed.  Added a description
                              of some of the considerations on how color
                              material should be treated.  Added issues on the
                              name of the program matrices, the number of MVP
                              matrices, and where variable declarations 
                              can be done.  Added numbers to all spec issues.
                              Fixed lighting example (issue 74) so it
                              compiles, and so that the half vector is
                              properly normalized.
                              
                              Grammar:  Eliminated stale hardwired temporary,
                              parameter array, and result register names
                              (R<n>, c[<n>], and o[...]).  Should have been
                              deleted going from revision 5 to revision 12.
                              Added missing program matrix bindings to the
                              grammar.  Eliminated state material-as-parameter
                              bindings.  Fixed texgen paramete bindings, which
                              should have had both "eye" and "object" planes.
                              Added separate address register write masks and
                              selectors to reflect the current single-
                              component address register restriction.  Added
                              an array[A0.x] rule -- before, you erroneously
                              had to add or subtract a constant.  Modified SWZ
                              so that the register being swizzled can't take a
                              conventional swizzle suffix, too.

                              Also reorganized grammar to closely mirror the
                              sample implementation, consolidating a number of
                              redundant rules.  Also fixed several bugs
                              found by the implementation.

                              Documentation changes to "LIT" to use the right
                              variable name and also indicate that 0^0=1.
                              Fixed the computation of result.y in the "LOG"
                              instruction.

                              Other:  Added dependency on ARB_imaging.  Added
                              notation of Microsoft's IP claims.  Fixed name
                              of MAX_VERTEX_PROGRAM_TEMPORARIES_ARB.

                              A few minor typo fixes.

    12    03/11/02  pbrown    Modified spec to reflect decisions made at
                              the March 2002 ARB meeting.  Distributed
                              to the OpenGL participants list.

    5     03/03/02  pbrown    Distributed to the ARB prior to March 2002
                              ARB meeting.
