Name

    NV_geometry_program4

Name Strings

    (none)

Contact

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

Status

    Shipping for GeForce 8 Series (November 2006)

Version

    Last Modified Date:         12/14/09
    NVIDIA Revision:            13

Number

    323

Dependencies

    OpenGL 1.1 is required.

    This extension is written against the OpenGL 2.0 specification.

    NV_gpu_program4 is required.  This extension is supported if
    "GL_NV_gpu_program4" is found in the extension string.

    EXT_framebuffer_object interacts with this extension.

    EXT_framebuffer_blit interacts with this extension.

    EXT_texture_array interacts with this extension.

    ARB_texture_rectangle trivially affects the definition of this extension.

    EXT_texture_buffer_object trivially affects the definition of this
    extension.

    NV_primitive_restart trivially affects the definition of this extension.

Overview

    NV_geometry_program4 defines a new type of program available to be run on
    the GPU, called a geometry program.  Geometry programs are run on full
    primitives after vertices are transformed, but prior to flat shading and
    clipping.

    A geometry program begins with a single primitive - a point, line, or
    triangle.  Quads and polygons are allowed, but are decomposed into
    individual triangles prior to geometry program execution.  It can read the
    attributes of any of the vertex in the primitive and use them to generate
    new primitives.  A geometry program has a fixed output primitive type,
    either a point, a line strip, or a triangle strip.  It emits vertices
    (using the EMIT opcode) to define the output primitive.  The attributes of
    emitted vertices are specified by writing to the same set of result
    bindings (e.g., "result.position") provided for vertex programs.
    Additionally, a geometry program can emit multiple disconnected primitives
    by using the ENDPRIM opcode, which is roughly equivalent to calling End
    and then Begin again.  The primitives emitted by the geometry program are
    then clipped and then processed like an equivalent OpenGL primitive
    specified by the application.

    This extension provides four additional primitive types:  lines with
    adjacency, line strips with adjacency, separate triangles with adjacency,
    and triangle strips with adjacency.  Some of the vertices specified in
    these new primitive types are not part of the ordinary primitives.
    Instead, they represent neighboring vertices that are adjacent to the two
    line segment end points (lines/strips) or the three triangle edges
    (triangles/tstrips).  These "adjacency" vertices can be accessed by
    geometry programs and used to match up the outputs of the geometry program
    with those of neighboring primitives.

    Additionally, geometry programs allow for layered rendering, where entire
    three-dimensional, cube map, or array textures (EXT_texture_array) can be
    bound to the current framebuffer.  Geometry programs can use the
    "result.layer" binding to select a layer or cube map face to render to.
    Each primitive emitted by such a geometry program is rendered to the layer
    taken from its provoking vertex.

    Since geometry programs expect a specific input primitive type, an error
    will occur if the application presents primtives of a different type.  For
    example, if an enabled geometry program expects points, an error will
    occur at Begin() time, if a primitive mode of TRIANGLES is specified.

New Procedures and Functions

    void ProgramVertexLimitNV(enum target, int limit);

    void FramebufferTextureEXT(enum target, enum attachment,
                               uint texture, int level);
    void FramebufferTextureLayerEXT(enum target, enum attachment,
                                    uint texture, int level, int layer);
    void FramebufferTextureFaceEXT(enum target, enum attachment,
                                   uint texture, int level, enum face);

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:

        GEOMETRY_PROGRAM_NV                             0x8C26

    Accepted by the <pname> parameter of GetProgramivARB:

        MAX_PROGRAM_OUTPUT_VERTICES_NV                  0x8C27
        MAX_PROGRAM_TOTAL_OUTPUT_COMPONENTS_NV          0x8C28
        GEOMETRY_VERTICES_OUT_EXT                       0x8DDA
        GEOMETRY_INPUT_TYPE_EXT                         0x8DDB
        GEOMETRY_OUTPUT_TYPE_EXT                        0x8DDC

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

        MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT            0x8C29

    Accepted by the <mode> parameter of Begin, DrawArrays, MultiDrawArrays,
    DrawElements, MultiDrawElements, and DrawRangeElements:

        LINES_ADJACENCY_EXT                             0xA
        LINE_STRIP_ADJACENCY_EXT                        0xB
        TRIANGLES_ADJACENCY_EXT                         0xC
        TRIANGLE_STRIP_ADJACENCY_EXT                    0xD

    Returned by CheckFramebufferStatusEXT:

        FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT        0x8DA8
        FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT          0x8DA9

    Accepted by the <pname> parameter of
    GetFramebufferAttachmentParameterivEXT:

        FRAMEBUFFER_ATTACHMENT_LAYERED_EXT              0x8DA7
        FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT        0x8CD4

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

        PROGRAM_POINT_SIZE_EXT                          0x8642

    (Note:  The "EXT" tokens above are shared with the EXT_geometry_shader4
    extension.)

    (Note:  FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER is simply an alias for the
    FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT token provided in
    EXT_framebuffer_object.  This extension generalizes the notion of
    "<zoffset>" to include layers of an array texture.)

    (Note:  PROGRAM_POINT_SIZE_EXT is simply an alias for the
    VERTEX_PROGRAM_POINT_SIZE token provided in OpenGL 2.0, which is itself an
    alias for VERTEX_PROGRAM_POINT_SIZE_ARB provided by ARB_vertex_program.
    Program-computed point sizes can be enabled if geometry programs are
    enabled, even if no vertex program is used.)
        
Additions to Chapter 2 of the OpenGL 1.5 Specification (OpenGL Operation)

    Modify Section 2.6.1 (Begin and End Objects), p. 13

    (Add to end of section, p. 18)

    (add figure)

        1 - - - 2----->3 - - - 4     1 - - - 2--->3--->4--->5 - - - 6

        5 - - - 6----->7 - - - 8

               (a)                             (b)

      Figure X.1 (a) Lines with adjacency, (b) Line strip with adjacency. 
      The vertices connected with solid lines belong to the main primitives;
      the vertices connected by dashed lines are the adjacent vertices that
      may be used in a geometry program.

    Lines with Adjacency

    Lines with adjacency are independent line segments where each endpoint has
    a corresponding "adjacent" vertex that can be accessed by a geometry
    program (Section 2.15).  If geometry programs are disabled, the "adjacent"
    vertices are ignored.

    A line segment is drawn from the 4i + 2nd vertex to the 4i + 3rd vertex
    for each i = 0, 1, ... , n-1, where there are 4n+k vertices between the
    Begin and End.  k is either 0, 1, 2, or 3; if k is not zero, the final k
    vertices are ignored.  For line segment i, the 4i + 1st and 4i + 4th
    vertices are considered adjacent to the 4i + 2nd and 4i + 3rd vertices,
    respectively.  See Figure X.1.

    Lines with adjacency are generated by calling Begin with the argument
    value LINES_ADJACENCY_EXT.

    Line Strips with Adjacency

    Line strips with adjacency are similar to line strips, except that each
    line segment has a pair of adjacent vertices that can be accessed by
    geometry programs (Section 2.15).  If geometry programs are disabled, the
    "adjacent" vertices are ignored.

    A line segment is drawn from the i + 2nd vertex to the i + 3rd vertex for
    each i = 0, 1, ..., n-1, where there are n+3 vertices between the Begin
    and End.  If there are fewer than four vertices between a Begin and End,
    all vertices are ignored.  For line segment i, the i + 1st and i + 4th
    vertices are considered adjacent to the i + 2nd and i + 3rd vertices,
    respectively.  See Figure X.1.

    Line strips with adjacency are generated by calling Begin with the
    argument value LINE_STRIP_ADJACENCY_EXT.

    (add figure)
                   2 - - - 3 - - - 4     8 - - - 9 - - - 10
                           ^\                    ^\
                     \     | \     |       \     | \     |
                           |  \                  |  \
                       \   |   \   |         \   |   \   |
                           |    \                |    \
                         \ |     \ |           \ |     \ |
                           |      v              |      v
                           1<------5             7<------11

                             \     |               \     |

                               \   |                 \   |

                                 \ |                   \ |

                                   6                     12

      Figure X.2 Triangles with adjacency.  The vertices connected with solid
      lines belong to the main primitive; the vertices connected by dashed
      lines are the adjacent vertices that may be used in a geometry program.

    Triangles with Adjacency

    Triangles with adjacency are similar to separate triangles, except that
    each triangle edge has an adjacent vertex that can be accessed by geometry
    programs (Section 2.15).  If geometry programs are disabled, the
    "adjacent" vertices are ignored.

    The 6i + 1st, 6i + 3rd, and 6i + 5th vertices (in that order) determine a
    triangle for each i = 0, 1, ..., n-1, where there are 6n+k vertices
    between the Begin and End.  k is either 0, 1, 2, 3, 4, or 5; if k is
    non-zero, the final k vertices are ignored.  For triangle i, the i + 2nd,
    i + 4th, and i + 6th vertices are considered adjacent to edges from the i
    + 1st to the i + 3rd, from the i + 3rd to the i + 5th, and from the i +
    5th to the i + 1st vertices, respectively.  See Figure X.2.

    Triangles with adjacency are generated by calling Begin with the argument
    value TRIANGLES_ADJACENCY_EXT.

    (add figure)
                                  6                     6

                                  | \                   | \

                                  |   \                 |   \

                                  |     \               |     \

      2 - - - 3- - - >6   2 - - - 3------>7     2 - - - 3------>7- - - 10
              ^\                  ^^      |             ^^      ^^      |
        \     | \     |     \     | \     | \     \     | \     | \
              |  \                |  \    |             |  \    |  \    |
          \   |   \   |       \   |   \   |   \     \   |   \   |   \
              |    \              |    \  |             |    \  |    \  |
            \ |     \ |         \ |     \ |     \     \ |     \ |     \
              |      v            |      vv             |      vv      v|
              1<------5           1<------5 - - - 8     1<------5<------9

                \     |             \     |               \     | \     |

                  \   |               \   |                 \   |   \   |

                    \ |                 \ |                   \ |     \ |

                      4                   4                     4       8


                                   6       10

                                   | \     | \

                                   |   \   |   \

                                   |     \ |     \
                           2 - - - 3------>7------>11
                                   ^^      ^^      |
                             \     | \     | \     | \
                                   |  \    |  \    |
                               \   |   \   |   \   |   \
                                   |    \  |    \  |
                                 \ |     \ |     \ |     \
                                   |      vv      vv
                                   1<------5<------9 - - - 12

                                     \     | \     |

                                       \   |   \   |

                                         \ |     \ |

                                           4       8

      Figure X.3 Triangle strips with adjacency.  The vertices connected with
      solid lines belong to the main primitives; the vertices connected by
      dashed lines are the adjacent vertices that may be used in a geometry
      program.

    Triangle Strips with Adjacency

    Triangle strips with adjacency are similar to triangle strips, except that
    each triangle edge has an adjacent vertex that can be accessed by geometry
    programs (Section 2.15).  If geometry programs are disabled, the
    "adjacent" vertices are ignored.

    In triangle strips with adjacency, n triangles are drawn using 2 * (n+2) +
    k vertices between the Begin and End.  k is either 0 or 1; if k is 1, the
    final vertex is ignored.  If fewer than 6 vertices are specified between
    the Begin and End, the entire primitive is ignored.  Table X.1 describes
    the vertices and order used to draw each triangle, and which vertices are
    considered adjacent to each edge of the triangle.  See Figure X.3.

    (add table)
                                 primitive          adjacent
                                 vertices           vertices
      primitive               1st   2nd   3rd     1/2  2/3  3/1
      ---------------        ----  ----  ----    ---- ---- ----
      only (i==0, n==1)        1     3     5       2    6    4
      first (i==0)             1     3     5       2    7    4
      middle (i odd)         2i+3  2i+1  2i+5    2i-1 2i+4 2i+7
      middle (i even)        2i+1  2i+3  2i+5    2i-1 2i+7 2i+4
      last (i==n-1, i odd)   2i+3  2i+1  2i+5    2i-1 2i+4 2i+6
      last (i==n-1, i even)  2i+1  2i+3  2i+5    2i-1 2i+6 2i+4

      Table X.1:  Triangles generated by triangle strips with adjacency.  
      Each triangle is drawn using the vertices in the "1st", "2nd", and "3rd"
      columns under "primitive vertices", in that order.  The vertices in the
      "1/2", "2/3", and "3/1" columns under "adjacent vertices" are considered
      adjacent to the edges from the first to the second, from the second to
      the third, and from the third to the first vertex of the triangle,
      respectively.  The six rows correspond to the six cases:  the first and
      only triangle (i=0, n=1), the first triangle of several (i=0, n>0),
      "odd" middle triangles (i=1,3,5...), "even" middle triangles
      (i=2,4,6,...), and special cases for the last triangle inside the
      Begin/End, when i is either even or odd.  For the purposes of this
      table, the first vertex specified after Begin is numbered "1" and the
      first triangle is numbered "0".

    Triangle strips with adjacency are generated by calling Begin with the
    argument value TRIANGLE_STRIP_ADJACENCY_EXT.

    Modify Section 2.14.1, Lighting (p. 59)

    (modify fourth paragraph, p. 63) Additionally, vertex and geometry shaders
    and programs can operate in two-sided color mode, which is enabled and
    disabled by calling Enable or Disable with the symbolic value
    VERTEX_PROGRAM_TWO_SIDE.  When a vertex or geometry shader is active, the
    shaders can write front and back color values to the gl_FrontColor,
    gl_BackColor, gl_FrontSecondaryColor and gl_BackSecondaryColor outputs.
    When a vertex or geometry program is active, programs can write front and
    back colors using the available color result bindings.  When a vertex or
    geometry shader or program is active and two-sided color mode is enabled,
    the GL chooses between front and back colors, as described below.  If
    two-sided color mode is disabled, the front color output is always
    selected.

    Insert New Section 2.14.6, Geometry Programs (between 2.14.5, Color Index
    Lighting and 2.14.6, Clamping and Masking, p. 69)

    Section 2.14.6, Geometry Programs

    Each primitive may be optionally transformed by a geometry program.
    Geometry programs are enabled by calling Enable with the value
    GEOMETRY_PROGRAM_NV.  A geometry program takes a single input primitive
    and generates vertices to be arranged into one or more output primitives.
    The original input primitive is discarded, and the output primitives are
    processed in order by the remainder of the GL pipeline.

    Section 2.14.6.1, Geometry Program Input Primitives

    A geometry program can operate on one of five input primitive types, as
    specified by the mandatory "PRIMITIVE_IN" declaration.  Depending on the
    input primitive type, one to six vertices are available when the program
    is executed.  A geometry program will fail to load unless it contains
    exactly one such declaration.

    Each input primitive type supports only a subset of the primitives
    provided by the GL.  If geometry programs are enabled, Begin, or any
    function that implicitly calls Begin, will produce an INVALID_OPERATION
    error if the <mode> parameter is incompatible with the input primitive
    type of the current geometry program.

    The supported input primitive types are:

    Points (POINTS)

    Geometry programs that operate on points are valid only for the POINTS
    primitive type.  There is a only a single vertex available for each
    program invocation: "vertex[0]" refers to the single point.

    Lines (LINES)

    Geometry programs that operate on line segments are valid only for the
    LINES, LINE_STRIP, and LINE_LOOP primitive types.  There are two vertices
    available for each program invocation:  "vertex[0]" and "vertex[1]" refer
    to the beginning and end of the line segment.

    Lines with Adjacency (LINES_ADJACENCY)

    Geometry programs that operate on line segments with adjacent vertices are
    valid only for the LINES_ADJACENCY_EXT and LINE_STRIP_ADJACENCY_EXT
    primitive types.  There are four vertices available for each program
    invocation.  "vertex[1]" and "vertex[2]" refer to the beginning and end of
    the line segment.  "vertex[0]" and "vertex[3]" refer to the vertices
    adjacent to the beginning and end of the line segment, respectively.

    Triangles (TRIANGLES)

    Geometry programs that operate on triangles are valid for the TRIANGLES,
    TRIANGLE_STRIP, TRIANGLE_FAN, QUADS, QUAD_STRIP, and POLYGON primitive
    types.  

    When used with a geometry program that operates on triangles, QUADS,
    QUAD_STRIP, and POLYGON primitives are decomposed into triangles in an
    unspecified, implementation-dependent manner.  For convex polygons
    (already required in the core GL specification), this decomposition
    satisfies three properties:

      * the collection of triangles fully covers the area of the original
        primitive,

      * no two triangles in the decomposition overlap, and

      * the orientation of each triangle is consistent with the orientation of
        the original primitive.

    For such primitives, the program is executed once for each triangle in the
    decomposition.

    There are three vertices available for each program invocation.
    "vertex[0]", "vertex[1]", and "vertex[2]", refer to the first, second, and
    third vertex of the triangle, respectively.

    Triangles with Adjacency (TRIANGLES_ADJACENCY)

    Geometry programs that operate on triangles with adjacent vertices are
    valid for the TRIANGLES_ADJACENCY_EXT and TRIANGLE_STRIP_ADJACENCY_EXT
    primitive types.  There are six vertices available for each program
    invocation.  "vertex[0]", "vertex[2]", and "vertex[4]" refer to the first,
    second, and third vertex of the triangle respectively.  "vertex[1]",
    "vertex[3]", and "vertex[5]" refer to the vertices adjacent to the edges
    from the first to the second vertex, from the second to the third vertex,
    and from the third to the first vertex, respectively.

    Section 2.14.6.2, Geometry Program Output Primitives

    A geometry program can generate primitives of one of three types, as
    specified by the mandatory "PRIMITIVE_OUT" declaration.  A geometry
    program will fail to load unless it contains exactly one such declaration.

    The supported output primitive types are points (POINTS), line strips
    (LINE_STRIP), and triangle strips (TRIANGLE_STRIP).  The vertices output
    by the geometry program are decomposed into points, lines, or triangles
    based on the output primitive type in the manner described in section
    2.6.1.

    Section 2.14.6.3, Geometry Program Execution Environment

    Geometry programs execute using the instruction set documented in the
    GL_NV_gpu_program4 extension specification and in a manner similar to
    vertex programs.  Each vertex attribute access must identify the vertex
    number being accessed.  For example, "vertex[1].position" identifies the
    transformed position of "vertex[1]" as specified in teh description of the
    input primitive type.  Output vertices are specified by writing to vertex
    result variables in the same manner as done by vertex programs.

    The special instruction "EMIT" specifies that a vertex is completed.  A
    vertex is added to the current output primitive using the current values
    of the vertex result variables.  The values of any unwritten result
    variables (or components) are undefined.  

    After an EMIT instruction is completed, the current values of all vertex
    result variables become undefined.  If a program wants to ensure that the
    same result is used for every vertex written by the program, it is
    necessary to write the corresponding value once per vertex.

    The special instruction "ENDPRIM" specifies that the current output
    primitive should be completed and a new output primitive should be
    started.  A geometry program starts with an output primitive containing no
    vertices.  When a geometry program terminates, the current output
    primitive is automatically completed.  ENDPRIM has no effect if the
    geometry program's output primitive type is POINTS.

    When a primitive generated by a geometry program is completed, the
    vertices added by the EMIT instruction are decomposed into points, lines,
    or triangles according to the output primitive type in the manner
    described in Section 2.8.1.  The resulting primitives are then clipped and
    rasterized.  If the number of vertices emitted by the geometry program is
    not sufficient to produce a single primitive, nothing is drawn.

    Like vertex and fragment programs, geometry programs can access textures.
    The maximum number of texture image units that can be accessed by a
    geometry program is given by the value of
    MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT.

    Section 2.14.6.4, Geometry Program Output Limits

    A geometry program may not emit an unlimited number of vertices per
    invocation.  Each geometry program must declare a vertex limit, which is
    the maximum number of vertices that the program can ever produce.  The
    vertex limit is specified using the "VERTICES_OUT" declaration.  A
    geometry program will fail to load unless it contains exactly one such
    declaration.

    There are two implementation-dependent limits that limit the total number
    of vertices that a program can emit.  First, the vertex limit may not
    exceed the value of MAX_PROGRAM_OUTPUT_VERTICES_NV.  Second, product of
    the vertex limit and the number of result variable components written by
    the program (PROGRAM_RESULT_COMPONENTS_NV, as described in section 2.X.3.5
    of NV_gpu_program4) may not exceed the value of
    MAX_PROGRAM_TOTAL_OUTPUT_COMPONENTS_NV.  A geometry program will fail to
    load if its maximum vertex count or maximum total component count exceeds
    the implementation-dependent limit.  The limits may be queried by calling
    GetProgramiv with a <target> of GEOMETRY_PROGRAM_NV.  Note that the
    maximum number of vertices that a geometry program can emit may be much
    lower than MAX_PROGRAM_OUTPUT_VERTICES_NV if the program writes a large
    number of result variable components.

    After a geometry program is compiled, the vertex limit may be changed
    using the command

      void ProgramVertexLimitNV(enum target, int limit);

    <target> must be GEOMETRY_PROGRAM_NV.  <limit> is the new vertex limit,
    which must satisfy the two rules described above.  The error INVALID_VALUE
    is generated if <limit> is less than or equal to zero, <limit> is greater
    than or equal to MAX_PROGRAM_OUTPUT_VERTICES_NV, or if the total number of
    components emitted would exceed MAX_PROGRAM_TOTAL_OUTPUT_COMPONENTS_NV.
    The error INVALID_OPERATION is generated if the current geometry program
    has not been successfully loaded.

    When a program executes, the number of vertices it emits should not exceed
    the vertex limit.  Once a geometry program emits a number of vertices
    equal to the vertex limit, subsequent EMIT instructions may or may not
    have any effect.

    Modify Section 2.X.2, Program Grammar

    (replace third paragraph)

    Geometry programs are required to begin with the header string
    "!!NVgp4.0".  This header string identifies the subsequent program body as
    being a geometry program and indicates that it should be parsed according
    to the base NV_gpu_program4 grammar plus the additions below.  Program
    string parsing begins with the character immediately following the header
    string.

    (add the following grammar rules to the NV_gpu_program4 base grammar)

    <declSequence>          ::= <declaration> <declSequence>

    <instruction>           ::= <SpecialInstruction>

    <attribUseV>            ::= <attribVarName> <arrayMem> <arrayMem> 
                                <swizzleSuffix>

    <attribUseS>            ::= <attribVarName> <arrayMem> <arrayMem> 
                                <scalarSuffix>

    <attribUseVNS>          ::= <attribVarName> <arrayMem> <arrayMem>

    <resultUseW>            ::= <resultVarName> <arrayMem> <optWriteMask>
                              | <resultColor> <optWriteMask>
                              | <resultColor> "." <colorType> <optWriteMask>
                              | <resultColor> "." <faceType> <optWriteMask>
                              | <resultColor> "." <faceType> "." <colorType> 
                                "." <optWriteMask>

    <resultUseD>            ::= <resultColor>
                              | <resultColor> "." <colorType>
                              | <resultMulti>

    <declaration>           ::= "PRIMITIVE_IN" <declPrimInType>
                              | "PRIMITIVE_OUT" <declPrimOutType>
                              | "VERTICES_OUT" <int>

    <declPrimInType>        ::= "POINTS"
                              | "LINES"
                              | "LINES_ADJACENCY"
                              | "TRIANGLES"
                              | "TRIANGLES_ADJACENCY"

    <declPrimOutType>       ::= "POINTS"
                              | "LINE_STRIP"
                              | "TRIANGLE_STRIP"

    <SpecialInstruction>    ::= "EMIT"
                              | "ENDPRIM"

    <attribBasic>           ::= <vtxPrefix> "position"
                              | <vtxPrefix> "fogcoord"
                              | <vtxPrefix> "pointsize"
                              | <vtxPrefix> "id"
                              | <attribTexCoord> <optArrayMemAbs>
                              | <attribClip> <arrayMemAbs>
                              | <attribGeneric> <arrayMemAbs>
                              | "primitive" "." "id"

    <attribColor>           ::= <vtxPrefix> "color"

    <attribMulti>           ::= <attribTexCoord> <arrayRange>
                              | <attribClip> <arrayRange>
                              | <attribGeneric> <arrayRange>

    <attribTexCoord>        ::= <vtxPrefix> "texcoord"

    <attribClip>            ::= <vtxPrefix> "clip"

    <attribGeneric>         ::= <vtxPrefix> "attrib"

    <vtxPrefix>             ::= "vertex" <optArrayMemAbs>

    <resultBasic>           ::= <resPrefix> "position"
                              | <resPrefix> "fogcoord"
                              | <resPrefix> "pointsize"
                              | <resPrefix> "primid"
                              | <resPrefix> "layer"
                              | <resultTexCoord> <optArrayMemAbs>
                              | <resultClip> <arrayMemAbs>
                              | <resultGeneric> <arrayMemAbs>

    <resultColor>           ::= <resPrefix> "color"

    <resultMulti>           ::= <resultTexCoord> <arrayRange>
                              | <resultClip> <arrayRange>
                              | <resultGeneric> <arrayRange>

    <resultTexCoord>        ::= <resPrefix> "texcoord"

    <resultClip>            ::= <resPrefix> "clip"

    <resultGeneric>         ::= <resPrefix> "attrib"

    <resPrefix>             ::= "result" "."

    (add the following subsection to section 2.X.3.2, Program Attribute
    Variables)

    Geometry program attribute variables describe the attributes of each
    transformed vertex accessible to the geometry program.  Most attributes
    correspond to the per-vertex results generated by vertex program execution
    or fixed-function vertex processing.  The "primitive.id" attribute is
    generated specially, as described below.

    If vertex programs are enabled, attributes will be obtained from the
    per-vertex outputs of the vertex program used to generate the vertex in
    question.  Geometry program attributes should be read using the same
    component data type used to write the corresponding vertex program
    results.  The value of any attribute corresponding to a vertex output not
    written by the vertex program is undefined.

    If vertex programs are disabled, attributes will be obtained from the
    values computed by fixed-function vertex processing.  All attributes,
    except for the primitive ID should be read as floating-point values in
    this case.

      Geometry Vertex Binding         Components  Description
      -----------------------------   ----------  ----------------------------
      vertex[m].position              (x,y,z,w)   clip coordinates
      vertex[m].color                 (r,g,b,a)   front primary color
      vertex[m].color.primary         (r,g,b,a)   front primary color
      vertex[m].color.secondary       (r,g,b,a)   front secondary color
      vertex[m].color.front           (r,g,b,a)   front primary color
      vertex[m].color.front.primary   (r,g,b,a)   front primary color
      vertex[m].color.front.secondary (r,g,b,a)   front secondary color
      vertex[m].color.back            (r,g,b,a)   back primary color
      vertex[m].color.back.primary    (r,g,b,a)   back primary color
      vertex[m].color.back.secondary  (r,g,b,a)   back secondary color
      vertex[m].fogcoord              (f,-,-,-)   fog coordinate
      vertex[m].pointsize             (s,-,-,-)   point size
      vertex[m].texcoord              (s,t,r,q)   texture coordinate, unit 0
      vertex[m].texcoord[n]           (s,t,r,q)   texture coordinate, unit n
      vertex[m].attrib[n]             (x,y,z,w)   generic interpolant n
      vertex[m].clip[n]               (d,-,-,-)   clip plane distance
      vertex[m].texcoord[n..o]        (s,t,r,q)   array of texture coordinates
      vertex[m].attrib[n..o]          (x,y,z,w)   array of generic interpolants
      vertex[m].clip[n..o]            (d,-,-,-)   array of clip distances
      vertex[m].id                    (id,-,-,-)  vertex id
      primitive.id                    (id,-,-,-)  primitive number

      Table X.2, Geometry Program Attribute Bindings.  <m> refers to a vertex
      number, while <n>, and <o> refer to integer constants.  Only the
      "vertex[m].texcoord" and "vertex.attrib" bindings are available in
      arrays.

    For bindings that include "vertex[m]", <m> identifies the vertex number
    whose attributes are used for the binding.  For bindings in explicit
    variable declarations, "[m]" is optional.  If "[m]" is specified, <m> must
    be an integer constant and must be in the valid range of vertices
    supported for the input primitive type.  If "[m]" is not specified, the
    declared variable is accessed as an array, with the first array index
    specifying the vertex number.  If such a variable is declared an array, it
    must have a second array index to identify the individual array element.
    For bindings used directly in instructions, "[m]" is required and must be
    an integer constant specifying a vertex number.  The following examples
    illustrate various legal and illegal geometry program bindings and their
    meanings.

      ATTRIB pos = vertex.position;
      ATTRIB pos2 = vertex[2].position;
      ATTRIB texcoords[] = { vertex.texcoord[0..3] };
      ATTRIB tcoords1[4] = { vertex[1].texcoord[1..4] };
      INT TEMP A0;
      ...
      MOV R0, pos[1];                   # position of vertex 1
      MOV R0, vertex[1].position;       # position of vertex 1
      MOV R0, pos2;                     # position of vertex 2
      MOV R0, texcoords[A0.x][1];       # texcoord 1 of vertex A0.x
      MOV R0, texcoords[A0.x][A0.y];    # texcoord A0.y of vertex A0.x
      MOV R0, tcoords1[2];              # texcoord 3 of vertex 1
      MOV R0, vertex[A0.x].texcoord[1]; # ILLEGAL allowed -- vertex number
                                        #    must be constant here.

    If a geometry attribute binding matches "vertex[m].position", the "x",
    "y", "z" and "w" components of the geometry attribute variable are filled
    with the "x", "y", "z", and "w" components, respectively, of the
    transformed position of vertex <m>, in clip coordinates.

    If a geometry attribute binding matches any binding in Table X.2 beginning
    with "vertex[m].color", the "x", "y", "z", and "w" components of the
    geometry attribute variable are filled with the "r", "g", "b", and "a"
    components, respectively, of the corresponding color of vertex <m>.
    Bindings containing "front" and "back" refer to the front and back colors,
    respectively.  Bindings containing "primary" and "secondary" refer to
    primary and secondary colors, respectively.  If face or color type is
    omitted in the binding, the binding is treated as though "front" and
    "primary", respectively, were specified.

    If a geometry attribute binding matches "vertex[m].fogcoord", the "x"
    component of the geometry attribute variable is filled with the fog
    coordinate of vertex <m>.  The "y", "z", and "w" components are undefined.

    If a geometry attribute binding matches "vertex[m].pointsize", the "x"
    component of the geometry attribute variable is filled with the point size
    of vertex <m> computed by the vertex program.  For fixed-function vertex
    processing, the point size attribute is undefined.  The "y", "z", and "w"
    components are always undefined.

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

    If a geometry attribute binding matches "vertex[m].attrib[n]", the "x",
    "y", "z", and "w" components of the geometry attribute variable are filled
    with the "x", "y", "z", and "w" coordinates of generic interpolant <n> of
    vertex <m>.  All generic interpolants will be undefined when used with
    fixed-function vertex processing.

    If a geometry attribute binding matches "vertex[m].clip[n]", the "x"
    component of the geometry attribute variable is filled the clip distance
    of vertex <m> for clip plane <n>, as written by the vertex program.  If
    fixed-function vertex processing or position-invariant vertex programs are
    used, the clip distance is obtained by computing the per-clip plane dot
    product:

      (p_1' p_2' p_3' p_4') dot (x_e y_e z_e w_e),

    at the vertex location, as described in section 2.12.  The clip distance
    for clip plane <n> is undefined if clip plane <n> is disabled.  The "y",
    "z", and "w" components of the attribute are undefined.

    If a geometry attribute binding matches "vertex[m].texcoord[n..o]",
    "vertex[m].attrib[n..o]", or "vertex[m].clip[n..o]", a sequence of
    1+<o>-<n> texture coordinate bindings is created.  For texture coordinate
    bindings, it is as though the sequence "vertex[m].texcoord[n],
    vertex[m].texcoord[n+1], ... vertex[m].texcoord[o]" were specfied.  These
    bindings are available only in explicit declarations of array variables.
    A program will fail to load if <n> is greater than <o>.

    If a geometry attribute binding matches "vertex[m].id", the "x" component
    is filled with the vertex ID.  If a vertex program is currently active,
    the attribute variable is filled with the vertex ID result written by the
    vertex program.  If fixed-function vertex processing is used, the vertex
    ID is undefined.  The "y", "z", and "w" components of the attribute are
    undefined.

    If a geometry attribute binding matches "primitive.id", the "x" component
    is filled with the number of primitives received by the GL since the last
    time Begin was called (directly or indirectly via vertex array functions).
    The first primitive generated after a Begin is numbered zero, and the
    primitive ID counter is incremented after every individual point, line, or
    polygon primitive is processed.  For QUADS and QUAD_STRIP primitives that
    are decomposed into triangles, the primitive ID is incremented after each
    complete quad is processed.  For POLYGON primitives, the primitive ID
    counter is zero.  Restarting a primitive topology using the primitive
    restart index has no effect on the primitive ID counter.  The "y", "z",
    and "w" components of the variable are always undefined.

    (add the following subsection to section 2.X.3.5, Program Results.)

    Geometry programs emit vertices, and the set of result variables available
    to such programs correspond to the attributes of each emitted vertex.  The
    set of allowable result variable bindings for geometry programs is given
    in Table X.3.

      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
      result.attrib[n]               (x,y,z,w)   generic interpolant n
      result.clip[n]                 (d,*,*,*)   clip plane distance
      result.texcoord[n..o]          (s,t,r,q)   texture coordinates n thru o
      result.attrib[n..o]            (x,y,z,w)   generic interpolants n thru o
      result.clip[n..o]              (d,*,*,*)   clip distances n thru o
      result.primid                  (id,*,*,*)  primitive id
      result.layer                   (l,*,*,*)   layer for cube/array/3D FBOs

      Table X.3:  Geometry Program 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.3.  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.

    If a result variable binding matches "result.attrib[n]", updates to the
    "x", "y", "z", and "w" components of the result variable set the "x", "y",
    "z", and "w" components of the generic interpolant <n>.

    If a result variable binding matches "result.clip[n]", updates to the "x"
    component of the result variable set the clip distance for clip plane <n>.

    If a result variable binding matches "result.texcoord[n..o]",
    "result.attrib[n..o]", or "result.clip[n..o]", a sequence of 1+<o>-<n>
    bindings is created.  For texture coordinates, it is as though the
    sequence "result.texcoord[n], result.texcoord[n+1],
    ... result.texcoord[o]" were specfied.  These bindings are available only
    in explicit declarations of array variables.  A program will fail to load
    if <n> is greater than <o>.

    If a result variable binding matches "result.primid", updates to the "x"
    component of the result variable provide a single integer that serves as a
    primitive identifier.  The written primitive ID is available to fragment
    programs using the "primitive.id" attribute binding.  If a fragment
    program using primitive IDs is active and a geometry program is also
    active, the geometry program must write "result.primid" or the primitive
    ID number is undefined.

    If a result variable binding matches "result.layer", updates to the "x"
    component of the result variable provide a single integer that serves as a
    layer selector for layered rendering (section 2.14.6.5).  The layer must
    be written as an integer value; writing a floating-point layer number will
    produce undefined results.

    (modify Table X.13 in section 2.X.4, Program Instructions, to include the
    following.)

                Modifiers 
    Instruction F I C S H D  Inputs     Out  Description
    ----------- - - - - - -  ---------- ---  --------------------------------
    EMIT        - - - - - -  -          -    emit vertex
    ENDPRIM     - - - - - -  -          -    end of primitive

    (add the following subsection to section 2.X.6, Program Options.)

    Section 2.X.6.Y, Geometry Program Options

    No options are supported at present for geometry programs.

    (add the following subsection to section 2.X.7, Program Declarations.)

    Section 2.X.7.Y, Geometry Program Declarations

    Geometry programs support three types of declaration statements, as
    described below.  Each of the three must be included exactly once in the
    geometry program.

    - Input Primitive Type (PRIMITIVE_IN)

    The PRIMITIVE_IN statement declares the type of primitives seen by a
    geometry program.  The single argument must be one of "POINTS", "LINES",
    "LINES_ADJACENCY", "TRIANGLES", or "TRIANGLES_ADJACENCY".

    - Output Primitive Type (PRIMITIVE_OUT)

    The PRIMITIVE_OUT statement declares the type of primitive emitted by a
    geometry program.  The single argument must be one of "POINTS",
    "LINE_STRIP", or "TRIANGLE_STRIP".

    - Maximum Vertex Count (VERTICES_OUT)

    The VERTICES_OUT statement declares the maximum number of vertices that
    may be emitted by a geometry program.  The single argument must be a
    positive integer.  A vertex program that emits more than the specified
    number of vertices may terminate abnormally.

    (add the following subsections to section 2.X.8, Program Instruction Set.)

    Section 2.X.8.Z, EMIT:  Emit Vertex

    The EMIT instruction emits a new vertex to be added to the current output
    primitive of a geometry program.  The attributes of the emitted vertex are
    given by the current values of the vertex result variables.  After the
    EMIT instruction completes, a new vertex is started and all result
    variables become undefined.

    Section 2.X.8.Z, ENDPRIM:  End of Primitive

    A geometry program can emit multiple primitives in a single invocation.
    The ENDPRIM instruction is used in a geometry program to signify the end
    of the current primitive and the beginning of a new primitive of the same
    type.  The effect of ENDPRIM is roughly equivalent to calling End followed
    by a new Begin, where the primitive mode is specified in the text of the
    geometry program.

    Like End, the ENDPRIM instruction does not emit a vertex.  Any result
    registers written prior to an ENDPRIM instruction are unchanged, and will
    be used in the vertex specified by the next EMIT instruction if they are
    not overwritten first.

    When geometry program execution completes, the current primitive is
    automatically terminated.  It is not necessary to include an ENDPRIM
    instruction if the geometry program writes only a single primitive.

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

    Modify Section 3.3, Points (p. 95)

    (replace all Section 3.3 text on p. 95) A point is drawn by generating a
    set of fragments in the shape of a square or circle centered around the
    vertex of the point.  Each vertex has an associated point size that
    controls the size of that square or circle.

    If no vertex or geometry program is active, the size of the point is
    controlled by

      void PointSize(float size);

    <size> specifies the requested size of a point. The default value is
    1.0. A value less than or equal to zero results in the error
    INVALID_VALUE.

    The requested point size is multiplied with a distance attenuation factor,
    clamped to a specified point size range, and further clamped to the
    implementation-dependent point size range to produce the derived point
    size:

       derived size = clamp(size * sqrt(1/(a+b*d+c*d^2)))

    where d is the eye-coordinate distance from the eye, (0,0,0,1) in eye
    coordinates, to the vertex, and a, b, and c are distance attenuation
    function coefficients.

    If a vertex or geometry program is active, the derived size depends on the
    per-vertex point size mode enable.  Per-vertex point size mode is enabled
    or disabled by calling Enable or Disable with the symbolic value
    PROGRAM_POINT_SIZE_EXT.  If per-vertex point size is enabled and a geometry
    program is active, the point size is taken from the point size emitted by
    the geometry program.  If per-vertex point size is enabled an no geometry
    program is active, the point size is taken from the point size result of
    the vertex program.  Otherwise, the point size is taken from the <size>
    value provided to PointSize, with no distance attenuation applied.  In all
    cases, the point size is clamped to the implementation-dependent point
    size range.

    If multisampling is not enabled, the derived size is passed on to
    rasterization as the point width. ...

Additions to Chapter 4 of the OpenGL 1.5 Specification (Per-Fragment
Operations and the Frame Buffer)

    None.

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

    None.

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

    None.

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

    None.

Additions to the AGL/GLX/WGL Specifications

    None.

GLX Protocol

    The following rendering commands are sent to the server as part of a
    glXRender request:

    ProgramVertexLimitNV

        2           12               rendering command length
        2           4312             rendering command opcode
        4           ENUM             target
        4           INT32            limit


    The extension EXT_geometry_shader4 defines GLX protocol for
    the following non-rendering commands:

        FramebufferTextureEXT, FramebufferTextureLayerEXT,
        FramebufferTextureFaceEXT.

Errors

    The error INVALID_OPERATION is generated if Begin, or any command that
    implicitly calls Begin, is called when geometry program mode is enabled
    and the currently bound geometry program object does not contain a valid
    geometry program.

    The error INVALID_OPERATION is generated if Begin, or any command that
    implicitly calls Begin, is called when geometry program mode is enabled
    and:

      * the input primitive type of the current geometry program is POINTS and
        <mode> is not POINTS,

      * the input primitive type of the current geometry program is LINES and
        <mode> is not LINES, LINE_STRIP, or LINE_LOOP,

      * the input primitive type of the current geometry program is TRIANGLES
        and <mode> is not TRIANGLES, TRIANGLE_STRIP, TRIANGLE_FAN, QUADS,
        QUAD_STRIP, or POLYGON,

      * the input primitive type of the current geometry program is
        LINES_ADJACENCY and <mode> is not LINES_ADJACENCY_EXT or
        LINE_STRIP_ADJACENCY_EXT, or

      * the input primitive type of the current geometry program is
        TRIANGLES_ADJACENCY and <mode> is not TRIANGLES_ADJACENCY_EXT or
        TRIANGLE_STRIP_ADJACENCY_EXT.

    The error INVALID_ENUM is generated if GetProgramivARB is called with a 
    <pname> of MAX_PROGRAM_OUTPUT_VERTICES_NV or
    MAX_PROGRAM_TOTAL_OUTPUT_COMPONENTS_NV and the target isn't
    GEOMETRY_PROGRAM_NV.

Dependencies on EXT_framebuffer_object

    If EXT_framebuffer_object (or similar functionality) is not supported, the
    "result.layer" binding should be removed.  "FramebufferTextureEXT" and
    "FramebufferTextureLayerEXT" should be removed from "New Procedures and
    Functions", and FRAMEBUFFER_ATTACHMENT_LAYERED_EXT,
    FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT, and
    FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT should be removed from "New
    Tokens".

    Otherwise, this extension modifies EXT_framebuffer_object to add the
    notion of layered framebuffer attachments and framebuffers that can be
    used in conjunction with geometry programs to allow programs to direct
    primitives to a face of a cube map or layer of a three-dimensional texture
    or one- or two-dimensional array texture.  The layer used for rendering
    can be selected by the geometry program at run time.

    (insert before the end of Section 4.4.2, Attaching Images to Framebuffer
    Objects)

    There are several types of framebuffer-attachable images:

      * the image of a renderbuffer object, which is always two-dimensional,

      * a single level of a one-dimensional texture, which is treated as a
        two-dimensional image with a height of one,

      * a single level of a two-dimensional or rectangle texture,

      * a single face of a cube map texture level, which is treated as a
        two-dimensional image, or

      * a single layer of a one- or two-dimensional array texture or
        three-dimensional texture, which is treated as a two-dimensional
        image.

    Additionally, an entire level of a three-dimensional texture, cube map
    texture, or one- or two-dimensional array texture can be attached to an
    attachment point.  Such attachments are treated as an array of
    two-dimensional images, arranged in layers, and the corresponding
    attachment point is considered to be layered.

    (replace section 4.4.2.3, "Attaching Texture Images to a Framebuffer")

    GL supports copying the rendered contents of the framebuffer into the
    images of a texture object through the use of the routines
    CopyTexImage{1D|2D}, and CopyTexSubImage{1D|2D|3D}.  Additionally, GL
    supports rendering directly into the images of a texture object.

    To render directly into a texture image, a specified level of a texture
    object can be attached as one of the logical buffers of the currently
    bound framebuffer object by calling:

      void FramebufferTextureEXT(enum target, enum attachment,
                                 uint texture, int level);

    <target> must be FRAMEBUFFER_EXT.  <attachment> must be one of the
    attachment points of the framebuffer listed in table 1.nnn.

    If <texture> is zero, any image or array of images attached to the
    attachment point named by <attachment> is detached, and the state of the
    attachment point is reset to its initial values.  <level> is ignored if
    <texture> is zero.

    If <texture> is non-zero, FramebufferTextureEXT attaches level <level> of
    the texture object named <texture> to the framebuffer attachment point
    named by <attachment>.  The error INVALID_VALUE is generated if <texture>
    is not the name of a texture object, or if <level> is not a supported
    texture level number for textures of the type corresponding to <target>.
    The error INVALID_OPERATION is generated if <texture> is the name of a
    buffer texture.

    If <texture> is the name of a three-dimensional texture, cube map texture,
    or one- or two-dimensional array texture, the texture level attached to
    the framebuffer attachment point is an array of images, and the
    framebuffer attachment is considered layered.

    The command

      void FramebufferTextureLayerEXT(enum target, enum attachment,
                                      uint texture, int level, int layer);

    operates like FramebufferTextureEXT, except that only a single layer of
    the texture level, numbered <layer>, is attached to the attachment point.
    If <texture> is non-zero, the error INVALID_VALUE is generated if <layer>
    is negative, or if <texture> is not the name of a texture object.  The
    error INVALID_OPERATION is generated unless <texture> is zero or the name
    of a three-dimensional or one- or two-dimensional array texture.

    The command

      void FramebufferTextureFaceEXT(enum target, enum attachment,
                                     uint texture, int level, enum face);

    operates like FramebufferTextureEXT, except that only a single face of a
    cube map texture, given by <face>, is attached to the attachment point.
    <face> is one of TEXTURE_CUBE_MAP_POSITIVE_X, TEXTURE_CUBE_MAP_NEGATIVE_X,
    TEXTURE_CUBE_MAP_POSITIVE_Y, TEXTURE_CUBE_MAP_NEGATIVE_Y,
    TEXTURE_CUBE_MAP_POSITIVE_Z, TEXTURE_CUBE_MAP_NEGATIVE_Z. If <texture> is
    non-zero, the error INVALID_VALUE is generated if <texture> is not the
    name of a texture object.  The error INVALID_OPERATION is generated unless
    <texture> is zero or the name of a cube map texture.

    The command

      void FramebufferTexture1DEXT(enum target, enum attachment,
                                   enum textarget, uint texture, int level);

    operates identically to FramebufferTextureEXT, except for two additional
    restrictions.  If <texture> is non-zero, the error INVALID_ENUM is
    generated if <textarget> is not TEXTURE_1D and the error INVALID_OPERATION
    is generated unless <texture> is the name of a one-dimensional texture.

    The command

      void FramebufferTexture2DEXT(enum target, enum attachment,
                                   enum textarget, uint texture, int level);

    operates similarly to FramebufferTextureEXT.  If <textarget> is TEXTURE_2D
    or TEXTURE_RECTANGLE_ARB, <texture> must be zero or the name of a
    two-dimensional or rectangle texture.  If <textarget> is
    TEXTURE_CUBE_MAP_POSITIVE_X, TEXTURE_CUBE_MAP_NEGATIVE_X,
    TEXTURE_CUBE_MAP_POSITIVE_Y, TEXTURE_CUBE_MAP_NEGATIVE_Y,
    TEXTURE_CUBE_MAP_POSITIVE_Z, or TEXTURE_CUBE_MAP_NEGATIVE_Z, <texture>
    must be zero or the name of a cube map texture.  For cube map textures,
    only the single face of the cube map texture level given by <textarget> is
    attached.  The error INVALID_ENUM is generated if <texture> is not zero
    and <textarget> is not one of the values enumerated above.  The error
    INVALID_OPERATION is generated if <texture> is the name of a texture whose
    type does not match the texture type required by <textarget>.

    The command

      void FramebufferTexture3DEXT(enum target, enum attachment,
                                   enum textarget, uint texture,
                                   int level, int zoffset);

    behaves identically to FramebufferTextureLayerEXT, with the <layer>
    parameter set to the value of <zoffset>.  The error INVALID_ENUM is
    generated if <textarget> is not TEXTURE_3D.  The error INVALID_OPERATION
    is generated unless <texture> is zero or the name of a three-dimensional
    texture.

    For all FramebufferTexture commands, if <texture> is non-zero and the
    command does not result in an error, the framebuffer attachment state
    corresponding to <attachment> is updated based on the new attachment.
    FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT is set to TEXTURE,
    FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT is set to <texture>, and
    FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL is set to <level>.
    FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_FACE is set to <textarget> if
    FramebufferTexture2DEXT is called and <texture> is the name of a cubemap
    texture; otherwise, it is set to TEXTURE_CUBE_MAP_POSITIVE_X.
    FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT is set to <layer> or <zoffset> if
    FramebufferTextureLayerEXT or FramebufferTexture3DEXT is called;
    otherwise, it is set to zero.  FRAMEBUFFER_ATTACHMENT_LAYERED_EXT is set
    to TRUE if FramebufferTextureEXT is called and <texture> is the name of a
    three-dimensional texture, cube map texture, or one- or two-dimensional
    array texture; otherwise it is set to FALSE.

    (modify Section 4.4.4.1, Framebuffer Attachment Completeness -- add to the
    conditions necessary for attachment completeness)

    The framebuffer attachment point <attachment> is said to be "framebuffer
    attachment complete" if ...:

      * If FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT is TEXTURE and
        FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT names a three-dimensional
        texture, FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT must be smaller than
        the depth of the texture.

      * If FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT is TEXTURE and
        FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT names a one- or two-dimensional
        array texture, FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT must be
        smaller than the number of layers in the texture.

    (modify section 4.4.4.2, Framebuffer Completeness -- add to the list of
    conditions necessary for completeness)

      * If any framebuffer attachment is layered, all populated attachments
        must be layered.  Additionally, all populated color attachments must
        be from textures of the same target (i.e., three-dimensional, cube
        map, or one- or two-dimensional array textures).
        { FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT }

      * If any framebuffer attachment is layered, all attachments must have
        the same layer count.  For three-dimensional textures, the layer count
        is the depth of the attached volume.  For cube map textures, the layer
        count is always six.  For one- and two-dimensional array textures, the
        layer count is simply the number of layers in the array texture.
        { FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT }

    The enum in { brackets } after each clause of the framebuffer completeness
    rules specifies the return value of CheckFramebufferStatusEXT (see below)
    that is generated when that clause is violated. ...

    (add section 4.4.7, Layered Framebuffers)

    A framebuffer is considered to be layered if it is complete and all of its
    populated attachments are layered.  When rendering to a layered
    framebuffer, each fragment generated by the GL is assigned a layer number.
    The layer number for a fragment is zero if

      * the fragment is generated by DrawPixels, CopyPixels, or Bitmap,

      * geometry programs are disabled, or

      * the current geometry program does not contain an instruction that
        writes to the layer result binding.

    Otherwise, the layer for each point, line, or triangle emitted by the
    geometry program is taken from the layer output of the provoking vertex.
    For line strips, the provoking vertex is the second vertex of each line
    segment.  For triangle strips, the provoking vertex is the third vertex of
    each individual triangles.  The per-fragment layer can be different for
    fragments generated by each individual point, line, or triangle emitted by
    a single geometry program invocation.  A layer number written by a
    geometry program has no effect if the framebuffer is not layered.

    When fragments are written to a layered framebuffer, the fragment's layer
    number selects a single image from the array of images at each attachment
    point to use for the stencil test (section 4.1.5), depth buffer test
    (section 4.1.6), and for blending and color buffer writes (section 4.1.8).
    If the fragment's layer number is negative or greater than the number of
    layers attached, the effects of the fragment on the framebuffer contents
    are undefined.

    When the Clear command is used to clear a layered framebuffer attachment,
    all layers of the attachment are cleared.

    When commands such as ReadPixels or CopyPixels read from a layered
    framebuffer, the image at layer zero of the selected attachment is always
    used to obtain pixel values.

    When cube map texture levels are attached to a layered framebuffer, there
    are six layers attached, numbered zero through five.  Each layer number is
    mapped to a cube map face, as indicated in Table X.4.

      layer number   cube map face
      ------------   ---------------------------
           0         TEXTURE_CUBE_MAP_POSITIVE_X
           1         TEXTURE_CUBE_MAP_NEGATIVE_X
           2         TEXTURE_CUBE_MAP_POSITIVE_Y
           3         TEXTURE_CUBE_MAP_NEGATIVE_Y
           4         TEXTURE_CUBE_MAP_POSITIVE_Z
           5         TEXTURE_CUBE_MAP_NEGATIVE_Z

      Table X.4, Layer numbers for cube map texture faces.  The layers are
      numbered in the same sequence as the cube map face token values.

    (modify Section 6.1.3, Enumerated Queries -- Modify/add to list of <pname>
    values for GetFramebufferAttachmentParameterivEXT if
    FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT is TEXTURE)

      If <pname> is FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT and the attached
      image is a layer of a three-dimensional texture or one- or
      two-dimensional array texture, then <params> will contain the specified
      layer number.  Otherwise, <params> will contain the value zero.

      If <pname> is FRAMEBUFFER_ATTACHMENT_LAYERED_EXT, then <params> will
      contain TRUE if an entire level of a three-dimesional texture, cube map
      texture, or one- or two-dimensional array texture is attached to the
      <attachment>.  Otherwise, <params> will contain FALSE.

    (Modify the Additions to Chapter 5, section 5.4)

    Add the commands FramebufferTextureEXT, FramebufferTextureLayerEXT, and
    FramebufferTextureFaceEXT to the list of commands that are not compiled
    into a display list, but executed immediately.

Dependencies on EXT_framebuffer_blit

    If EXT_framebuffer_blit is supported, the EXT_framebuffer_object language
    should be further amended so that <target> values passed to
    FramebufferTextureEXT and FramebufferTextureLayerEXT can be
    DRAW_FRAMEBUFFER_EXT or READ_FRAMEBUFFER_EXT, and that those functions
    set/query state for the draw framebuffer if <target> is FRAMEBUFFER_EXT.

    If BlitFramebufferEXT() is called with a layered read framebuffer, pixel
    values are obtained from layer zero from the read framebuffer.  If the
    draw framebuffer is layered, pixel values are written to layer zero of the
    draw framebuffer.  If both framebuffers are layered, the two-dimensional
    blit operation is still performed only on layer zero.

Dependencies on EXT_texture_array

    If EXT_texture_array is not supported, the discussion array textures the
    layered rendering edits to EXT_framebuffer_object should be removed.
    Layered rendering to cube map and 3D textures would still be supported.

    If EXT_texture_array is supported, the edits to EXT_framebuffer_object
    supersede those made in EXT_texture_array, except for language pertaining
    to mipmap generation of array textures.  

    There are no functional incompatibilities between the FBO support in these
    two specifications.  The only differences are that this extension supports
    layered rendering and also rewrites certain sections of the core FBO
    specification more aggressively.

Dependencies on ARB_texture_rectangle

    If ARB_texture_rectangle is not supported, all references to rectangle
    textures in the EXT_framebuffer_object spec language should be removed.

Dependencies on EXT_texture_buffer_object

    If EXT_buffer_object is not supported, the reference to an
    INVALID_OPERATION error if a buffer texture is passed to
    FramebufferTextureEXT should be removed.

Dependencies on NV_primitive_restart

    The spec describes the behavior that primitive restart does not affect the
    primitive ID counter, including for POLYGON primitives (where one could
    argue that the restart index starts a new primitive without a new Begin to
    reset the count).  If NV_primitive_restart is not supported, references to
    that extension in the discussion of the "primitive.id" attribute should be
    removed.

New State
                                                       Initial
    Get Value                  Type    Get Command      Value  Description            Sec.    Attribute
    -------------------------  ----    -----------     ------- ---------------------- ------  ---------
    GEOMETRY_PROGRAM_NV         B      IsEnabled        FALSE  Geometry shader enable 2.14.6   enable
    FRAMEBUFFER_ATTACHMENT_    nxB     GetFramebuffer-  FALSE  Framebuffer attachment 4.4.2.3    -
      LAYERED_EXT                      Attachment-             is layered
                                       ParameterivEXT
    GEOMETRY_VERTICES_OUT_EXT   Z+     GetProgramivARB    0    vertex limit of the    2.14.6.4   -
                                                               current geometry 
                                                               program
    GEOMETRY_INPUT_TYPE_EXT     Z+     GetProgramivARB    0    input primitive type   2.14.6.4   -
                                                               of the current geometry 
                                                               program
    GEOMETRY_OUTPUT_TYPE_EXT    Z+     GetProgramivARB    0    output primitive type  2.14.6.4   -
                                                               of the current geometry 
                                                               program

New Implementation Dependent State

                                                              Minimum
    Get Value                        Type    Get Command      Value       Description             Sec           Attrib
    -------------------------------  ----    ---------------  ----------  --------------------    ------------  ------
    MAX_GEOMETRY_TEXTURE_            Z+      GetIntegerv      16          maximum number of       2.14.6.3      -
        IMAGE_UNITS_EXT                                                   texture image units
                                                                          accessible in a
                                                                          geometry program
    MAX_PROGRAM_OUTPUT_VERTICES_NV   Z+      GetProgramivARB  256         maximum number of       2.14.6.4      -
                                                                          vertices that any
                                                                          geometry program
                                                                          could emit
    MAX_PROGRAM_TOTAL_OUTPUT_        Z+      GetProgramivARB  1024        maximum number of       2.14.6.4      -
      COMPONENTS_NV                                                       result components (all
                                                                          vertices) that a
                                                                          geometry program
                                                                          can emit


NVIDIA Implementation Details

    Because of a hardware limitation, some GeForce 8 series chips use the
    odd vertex of an incomplete TRIANGLE_STRIP_ADJACENCY_EXT primitive
    as a replacement adjacency vertex rather than ignoring it.

Issues

    (1) How do geometry programs fit into the existing GL pipeline?

      RESOLVED:  The following diagram illustrates how geometry programs fit
      into the "vertex processing" portion of the GL (Chapter 2 of the OpenGL
      2.0 Specification).  

      First, vertex attributes are specified via immediate-mode commands or
      through vertex arrays.  They can be conventional attributes (e.g.,
      glVertex, glColor, glTexCoord) or generic (numbered) attributes.

      Vertices are then transformed, either using a vertex program or
      fixed-function vertex processing.  Fixed-function vertex processing
      includes position transformation (modelview and projection matrices),
      lighting, texture coordinate generation, and other calculations.  The
      results of either method are a "transformed vertex", which has a
      position (in clip coordinates), front and back colors, texture
      coordinates, generic attributes (vertex program only), and so on.  Note
      that on many current GL implementations, vertex processing is performed
      by executing a "fixed function vertex program" generated by the driver.

      After vertex transformation, vertices are assembled into primitives,
      according to the topology (e.g., TRIANGLES, QUAD_STRIP) provided by the
      call to glBegin().  Primitives are points, lines, triangles, quads, or
      polygons.  Many GL implementations do not directly support quads or
      polygons, but instead decompose them into triangles as permitted by the
      spec.

      After initial primitive assembly, a geometry program is executed on each
      individual point, line, or triangle primitive, if enabled.  It can read
      the attributes of each transformed vertex, perform arbitrary
      computations, and emit new transformed vertices.  These emitted vertices
      are themselves assembled into primitives according to the output
      primitive type of the geometry program.

      Then, the colors of the vertices of each primitive are clamped to [0,1]
      (if color clamping is enabled), and flat shading may be performed by
      taking the color from the provoking vertex of the primitive.

      Each primitive is clipped to the view volume, and to any enabled
      user-defined clip planes.  Color, texture coordinate, and other
      attribute values are computed for each new vertex introduced by
      clipping.

      After clipping, the position of each vertex (in clip coordinates) is
      converted to normalized device coordinates in the perspective division
      (divide by w) step, and to window coordinates in the viewport
      transformation step.

      At the same time, color values may be converted to normalized
      fixed-point values according to the "Final Color Processing" portion of
      the specification.

      After the vertices of the primitive are transformed to window
      coordinate, the GL determines if the primitive is front- or back-facing.
      That information is used for two-sided color selection, where a single
      set of colors is selected from either the front or back colors
      associated with each transformed vertex.

      When all this is done, the final transformed position, colors (primary
      and secondary), and other attributes are used for rasterization (Chapter
      3 in the OpenGL 2.0 Specification).

      When the raster position is specified (via glRasterPos), it goes through
      the entire vertex processing pipeline as though it were a point.
      However, geometry programs are never run on the raster position.

                        |generic              |conventional
                        |vertex               |vertex
                        |attributes           |attributes
                        |                     |
                        | +-------------------+
                        | |                   |
                        V V                   V
                      vertex            fixed-function
                      program              vertex
                         |               processing
                         |                    |
                         |                    |
                         +<-------------------+                
                         |                                     Output
                         |position, color,                   Primitive
                         |other vertex data                     Type
                         |                                       |
                         V                                       |
        Begin/       primitive        geometry       primitive   |
         End ------> assembly  -----> program  ----> assembly  <-+
        State            |                               |
                         V                               |
                         +<------------------------------+
                         |
                         |
                         |             color            flat
                         +----------> clamping ---->  shading
                         |                               |
                         V                               |
                         +<------------------------------+
                         |
                         |
                      clipping
                         |
                         |        perspective       viewport
                         +------>   divide    ----> transform
                         |                              |
                         |                          +---+-----+
                         |                          V         |
                         |           final        facing      |
                         +------>    color     determination  |
                         |         processing       |         |
                         |             |            |         |
                         |             |            |         |
                         |             +-----+ +----+         |
                         |                   | |              |
                         |                   V V              |
                         |                two-sided           |
                         |                 coloring           |
                         |                    |               |
                         |                    |               |
                         +------------------+ | +-------------+
                                            | | |
                                            V V V
                                        rasterization 
                                              |
                                              |
                                              V

    (2) Why is this called GL_NV_geometry_program4?  There aren't any previous
    versions of this extension, let alone three?

      RESOLVED:  The instruction set for GPU programs of all types (vertex,
      fragment, and now geometry) have been unified in the GL_NV_gpu_program4
      extension, and the "4" suffix in this extension name indicates the
      instruction set type.  There are three previous NV_vertex_program
      variants (four if you count NV_vertex_program1_1), so "4" is the next
      available numeric suffix.

    (3) Should the GL produce errors at Begin time if an application specifies
    a primitive mode that is "incompatible" with the geometry program?  For
    example, if the geometry program operates on triangles and the application
    sends a POINTS primitive?

      RESOLVED:  Yes.  Mismatches of app-specified primitive types and
      geometry program input primitive types seem like clear errors and would
      produce weird and wonderful effects.

    (4) Can the input primitive type of a geometry program be changed at run
    time?

      RESOLVED:  Not in this extension.  Each geometry program has a single
      input primitive type, and vertices are presented to the program in a
      specific order based on that type.

    (5) Can the output primitive type of a geometry program be determined at
    run time?

      RESOLVED:  Not in this extension.

    (6) Must the output primitive type of a geometry program match the input
    primitive type in any way?

      RESOLVED:  No, you can have a geometry program generate points out of
      triangles or triangles out of points.  Some combinations are analogous
      to existing OpenGL operations:  reading triangles and writing points or
      line strips can be used to emulate a subset of PolygonMode
      functionality.  Reading points and writing triangle strips can be used
      to emulate point sprites.

    (7) Are primitives emitted by a geometry program processed like any other
    OpenGL primitive?

      RESOLVED:  Yes.  Antialiasing, stippling, polygon offset, polygon mode,
      culling, two-sided lighting and color selection, point sprite
      operations, and fragment processing all work as expected.  

      One limitation is that the only output primitive types supported are
      points, line strips, and triangle strips, none of which meaningfully
      support edge flags that are sometimes used in conjunction with the POINT
      and LINE polygon modes (edge flags are always ignored for line-mode
      triangle strips).

    (8) Should geometry programs support additional input primitive types?

      RESOLVED:  Possibly in a future extension.  It should be straightforward
      to build a future extension to support geometry programs that operate on
      quads.  Other primitive types might be more demanding on hardware.
      Quads with adjacency would require 12 vertices per program execution.
      General polygons may require even more, since there is no fixed bound on
      the number of vertices in a polygon.

    (9) Should geometry programs support additional output primitive types?

      RESOLVED:  Possibly in a future extension.  Additional output types
      (e.g., independent lines, line loops, triangle fans, polygons) may be
      useful in the future; triangle fans/polygons seem particularly useful.

    (10) Should we provide additional adjacency primitive types that can be
    used inside a Begin/End?

      RESOLVED:  Not in this extension.  It may be desirable to add new
      primitive types (e.g., TRIANGLE_FAN_ADJACENCY) in a future extension.

    (11) How do geometry programs interact with RasterPos?

      RESOLVED:  Geometry programs are ignored when specifying the raster
      position.  While the raster position could be treated as a point,
      turning it into a triangle strip would be quite bizarre.

    (12) How do geometry programs interact with pixel primitives (DrawPixels,
    Bitmap)?

      RESOLVED:  They do not.  Fragments generated be DrawPixels and Bitmap
      are injected into the pipeline after the point where geometry program
      execution occurs.

    (13) Is there a limit on the number of vertices that can be emitted by a
    geometry program?

      RESOLVED:  Unfortunately, yes.  Besides practical hardware limits, there
      may also be practical performance advantages when applications guarantee
      a tight upper bound on the number of vertices a geometry shader will
      emit.  GPUs frequently excecute programs in parallel, and there are
      substantial implementation challenges to parallel execution of geometry
      threads that can write an unbounded number of results, particular given
      that the all the primitives generated by the first geometry program
      invocation must be consumed before any of the primitives generated by
      the second program invocation.  Limiting the amount of data a geometry
      program can write substantially eases the implementation burden.

      A geometry program must declare a maximum number of vertices that can be
      emitted, called the vertex limit.  There is an implementation-dependent
      limit on the total number of vertices a program can emit (256 minimum)
      and the product of the vertex limit and the number of active result
      components (1024 minimum).  A program will fail to load if doesn't
      declare a limit or exceeds either of the two implementatoin-dependent
      limits.

      It would be ideal if the limit could be inferred from the instructions
      in the program itself, and that would be possible for many programs,
      particularly ones with straight-line flow control.  For programs with
      more complicated flow control (subroutines, data-dependent looping, and
      so on), it would be impossible to make such an inference and a "safe"
      limit would have to be used with adverse and possibly unexpected
      performance consequences.

      The limit on the number of EMIT instructions that can be issued can not
      always be enforced at compile time, or even at Begin time.  We specify
      that if a program tries to emit more vertices than the vertex limit
      allows, emits that exceed the limit may or may not have any effect.

    (14) Should it be possible to change the limit on the number of vertices
    emitted by a geometry program after the program is specified?

      RESOLVED:  Yes, using the function ProgramVertexLimitNV().  Applications
      may want to tweak a piece of data that affects the number of vertices
      emitted, but doesn't necessarily require recompiling the entire program.
      Examples might be a "circular point sprite" program, that reads a single
      point, and draws a circle centered at that point with <N> vertices.  An
      application could change the value <N> at run time, but it could require
      a change in the vertex limit.  Another example might be a geometry
      program that does some fancy subdivision, where the relevant parameter
      might be a limit on how far the primitive is subdivided.

      Ideally, this program object state should be set by a "program
      parameter" command, much like texture state is set by a "texture
      parameter" (TexParameter) command.  Unfortunately, there are already
      several different "program parameter" functions:

        ProgramEnvParameter4fARB()   -- sets global environment constants
        ProgramLocalParameter4fARB() -- sets per-program constants
        ProgramParameter4fNV()       -- also sets global environment constants

      Additionally, GLSL and OpenGL 2.0 introduced "program objects" which are
      linked collections of vertex, fragment, and now geometry shaders.  A
      GLSL vertex "shader" is equivalent to an ARB_vertex_program vertex
      "program", which is nothing like a GLSL program.  As of OpenGL 2.0, GLSL
      programs do not have settable parameters, by subsequent extensions may
      want to add them (for example, EXT_geometry_shader4, which has this same
      functionality for GLSL).  If that happens, they would want their own
      ProgramParameter API, but with a different prototype than this extension
      would want.

      Naming this function "ProgramVertexLimitNV" sidesteps this issue for
      now.

    (15) How do edge flags interact with adjacency primitives?

      RESOLVED:  If geometry programs are disabled, adjacency primitives are
      still supported.  For TRIANGLES_ADJACENCY_EXT, edge flags will apply as
      they do for TRIANGLES.  Such primitives are rendered as independent
      triangles as though the adjacency vertices were not provided.  Edge
      flags for the "real" vertices are supported.  For all other adjacency
      primitive types, edge flags are irrelevant.

    (16) How do geometry programs interact with color clamping?

      RESOLVED:  Geometry program execution occurs prior to color clamping in
      the pipeline.  This means the colors written by vertex programs or
      fixed-function vertex processing are not clamped to [0,1] before they
      are read by geometry programs.  If color clamping is enabled, any vertex
      colors written by the geometry program will have their components
      clamped to [0,1].

    (17) How are QUADS, QUAD_STRIP, and POLYGON primitives decomposed into
    triangles in the initial implementation of GL_NV_geometry_program4?

      RESOLVED:  The specification leaves the decomposition undefined, subject
      to a small number of rules.  Assume that four vertices are specified in
      the order V0, V1, V2, V3.

      For QUADS primitives, the quad V0->V1->V2->V3 is decomposed into the
      triangles V0->V1->V2, and V0->V2->V3.  The provoking vertex of the quad
      (V3) is only found in the second triangle.  If it's necessary to flat
      shade over an entire quad, take the attributes from V0, which will be
      the first vertex for both triangles in the decomposition.

      For QUAD_STRIP primitives, the quad V0->V1->V3->V2 is decomposed into
      the triangles V0->V1->V3 and V2->V0->V3.  This has the property of
      leaving the provoking vertex for the polygon (V3) as the third vertex
      for each triangle of the decomposition.

      For POLYGON primitives, the polygon V0->V1->V2->V3 is decomposed into
      the triangles V1->V2->V0 and V2->V3->V0.  This has the property of
      leaving the provoking vertex for the polygon (V0) as the third vertex
      for each triangle of the decomposition.

    (18) Should geometry programs be able to select a layer of a 3D texture,
    cube map texture, or array texture at run time?  If so, how?

      RESOLVED:  This extension provides a per-vertex result binding called
      "result.layer", which is an integer specifying the layer to render to.
      When an each individual point, line, or triangle is emitted by a
      geometry program, the layer number is taken from the provoking (last)
      vertex of the primitive and is used for all fragments generated by that
      primitive.

      The EXT_framebuffer_object (FBO) extension is used for rendering to
      textures, but for cube maps and 3D textures, it only provides the
      ability to attach a single face or layer of such textures.

      This extension generalizes FBO by creates new entry points to bind an
      entire texture level (FramebufferTextureEXT) or a single layer of a
      texture level (FramebufferTextureLayerEXT) to an attachment point.  The
      existing FBO binding functions, FramebufferTexture[123]DEXT are
      retained, and are defined in terms of the more general new functions.

      The new functions do not have a dimension in the function name or a
      <textarget> parameter, which can be inferred from the provided texture.
      They can do anything that the old functions can do, except attach a
      single face of a cube map texture.  We considered adding a separate
      function FramebufferTextureFaceEXT to provide this functionality, but
      decided that the existing FramebufferTexture2DEXT API was adequate.  We
      also considered using FramebufferTextureLayerEXT for this purpose, but
      it was not clear whether a layer number (0-5) or face enum (e.g,
      TEXTURE_CUBE_MAP_POSITIVE_X) should be provided.

      When an entire texel level of a cube map, 3D, or array texture is
      attached, that attachment is considered layered.  The framebuffer is
      considered layered if any attachment is layered.  When the framebuffer
      is layered, there are three additional completeness requirements:

        * all attachments must be layered
        * all color attachments must be from textures of identical type
        * all attachments must have the same number of layers

      We expect subsequent versions of the FBO spec to relax the requirement
      that all attachments must have the same width and height, and plan to
      relax the similar requirement for layer count at that time.

      When rendering to a layered framebuffer, layer zero is used unless a
      geometry program that writes the layer result is enabled.  When
      rendering to a non-layered framebuffer, any layer result emitted from
      geometry programs is ignored and the set of single-image attachments are
      used.  When reading from a layered framebuffer (e.g., ReadPixels), layer
      zero is always used.  When clearing a layered framebuffer, all layers
      are cleared to the corresponding clear values.

      Several other approaches were considered, including leveraging existing
      FBO attachment functions and requiring the use of FramebufferTexture3D
      with a <zoffset> of zero to make a framebuffer attachment "layerable"
      (attaching layer zero means that the attachment could be used for either
      layered- or non-layered rendering).  Whether rendering was layered or
      not could either be inferred from the active geometry program, or set as
      a new property of the framebuffer object.  There is presently
      FramebufferParameter API to set a property of a framebuffer, so it would
      have been necessary to create new set/query APIs if this approach were
      chosen.

    (19) How can single-pass cube map rendering be done efficiently in a
         geometry program?

      UNRESOLVED:  To do single-pass cubemap rendering, attach entire cube map
      textures to framebuffer attachment points using the new functions
      provided by this extension.  The vertex program used should only
      transform the vertex position to eye coordinates (position relative to
      the center of the cube map).  A geometry program should be used that
      effectively projects each input triangle onto each of the six faces of
      the cube map, emitting a triangle for each.  Each of the projected
      vertices should be emitted with a "result.layer" value matching the face
      number (0-5).  When the projected triangle is drawn, it is automatically
      drawn on the face corresponding to the emitted layer number.  

      It should be simple to skip projecting primitives onto faces they won't
      touch.  For example, if all of the X eye coordinates are positive, there
      is no reason to project to the "negative X" cube map face.

      An example should be provided for this issue.

    (20) How should per-vertex point size work with geometry programs?

      RESOLVED:  We will generalize the existing VERTEX_PROGRAM_POINT_SIZE
      enable to control the point size behavior if either vertex or geometry
      programs are enabled.

      If geometry programs are enabled, the point size is taken from the point
      size result of the emitted vertex if VERTEX_PROGRAM_POINT_SIZE is
      enabled, or from the PointSize state otherwise.

      If no geometry program is enabled, it works like OpenGL 2.0.  If a
      vertex program is active, it's taken from the point size result or
      PointSize state, depending on the VERTEX_PROGRAM_POINT_SIZE enable.  If
      no program is enabled, normal fixed-function point size handling
      (including distance attenuation) is supported.

      This extension creates a new alias for the VERTEX_PROGRAM_POINT_SIZE
      enum, called PROGRAM_POINT_SIZE_EXT, to reflect that the point size
      enable now covers multiple program types.  Both enums have the same
      value.

    (21) How do vertex IDs work with geometry programs?

      RESOLVED:  Vertex IDs are automatically provided to vertex programs
      when applicable, via the "vertex.id" binding.  However, they are not
      automatically copied the transformed vertex results that are read by
      geometry programs.

      Geometry programs can read the ID of vertex <n> via the
      "vertex[<n>].id" binding, but the vertex ID must have been copied by
      the vertex program using an instruction such as:

        MOV result.id.x, vertex.id.x;

      If a vertex program doesn't write vertex ID, or fixed-function vertex
      processing is used, the vertex ID visible to geometry programs is
      undefined.

    (22) How do primitive IDs work with geometry programs?

      RESOLVED:  Primitive IDs are automatically available to geometry
      programs via the "primitive.id" binding and indicate the number of
      input primitives previously processed since the last explicit or
      implicit Begin call.

      If a geometry program wants to make the primitive ID available to a
      fragment program, it should copy the appropriate value to the
      "result.primid" binding.

    (23) How do primitive IDs work with primitives not supported directly by
    geometry program input topologies (e.g., QUADS, POLYGON)?

      RESOLVED:  QUADS are decomposed into two triangles.  Both triangles
      will have the same primitive ID, which is the number of full quads
      previously processed.  POLYGON primitives are decomposed into a series
      of triangles, and all of them will have the primitive ID -- zero.

    (24) This is an NV extension (NV_geometry_program4).  Why do some of the
    new tokens have an "EXT" extension?

      RESOLVED:  Some of the tokens are shared between this extension and the
      comparable high-level GLSL programmability extension
      (EXT_geometry_shader4).  Rather than provide a duplicate set of tokens,
      we simply use the EXT versions here.  The tokens specific to assembly
      shader uses retain an NV suffix.

    (25) What happens if you try to do a framebuffer blit (via
        EXT_framebuffer_blit) to/from a layered framebuffer?

      RESOLVED:  BlitFramebufferEXT() is a two-dimensional operation (only has
      a width and height), so only reads/writes layer zero.  The framebuffer
      blit operation is defined partially in terms of CopyPixels, which itself
      is defined in terms of ReadPixels and DrawPixels.  This spec defines
      both operations to use layer zero when a layered framebuffer is
      involved.

      It may be desirable to provide a three-dimensional framebuffer blit
      operation or an explicit copy single-step operation between two
      three-dimensional, cube map, or array textures.  That functionality is
      left for a future extension or OpenGL version.


Revision History

    Rev.    Date    Author    Changes
    ----  --------  --------  --------------------------------------------
    13    12/14/09  mgodse    Added GLX protocol.
    
    12    07/21/09  pbrown    Clarify that when doing layered rendering,
                              a layer specified in the shader is used to
                              select the depth and stencil layers accessed.

                              Also document several additional entry points
                              that accept GEOMETRY_PROGRAM_NV.

    11    03/11/09  pbrown    Fix section numbers for option/declaration
                              sections.

    10    07/29/08  pbrown    Clean up garbled language describing vertex
                              output limits.

     9    04/04/08  pbrown    Fixed error in the state tables; the geometry
                              program enable should push/pop only with the
                              enable bit like all the other program enables.

     8    03/15/08  pbrown    Additional dependency on EXT_framebuffer_blit;
                              blits to/from layered targets affect only
                              layer zero.

     7    03/07/08  pbrown    Fix grammar to allow vertex ID, as already 
                              allowed in the rest of the spec body.

     6              pbrown    Internal spec development.

