Name
 
    EXT_direct_state_access

Name Strings

    GL_EXT_direct_state_access

Contributors

    Cass Everitt, NVIDIA
    Daniel Pageau, Blizzard
    Daniel Koch, TransGaming
    Ian Romanick, IBM
    Jason Green, TransGaming
    Johan Andersson, DICE/Electronic Arts
    Jon Leech
    Mark Kilgard, NVIDIA
    Nicholas Vining, Destineer
    Pat Brown, NVIDIA
    Patrick Doane, Blizzard
    Robert Barris, Blizzard
    Ryan Gordon, Destineer
    Scott Nations, NVIDIA
    Yanjun Zhang, S3 Graphics
    Jeff Bolz, NVIDIA
    Jeff Juliano, NVIDIA
    Jon Burgess, NVIDIA
    Mike Marcin
    Nigel Stewart, NVIDIA
    Jason McKesson
    Graham Sellers, AMD
    Vladimir Vukicevic, Mozilla

Contact

    Mark J. Kilgard, NVIDIA Corporation (mjk 'at' nvidia.com)

Status

    Complete, except for GLX protocol

    Version 1.0 implemented by NVIDIA, shipping November 2008
    Version 1.1 implemented by NVIDIA, shipping January 2009

Version

    Last Modified Date:         02/24/2014
    Author revision:            39
    Version                     1.2

    (version 1.0 lacked OpenGL 3.0 support)
    (version 1.1 lacked GL_TEXTUREi support for glVertexArrayTexCoordOffsetEXT)
    (version 1.1 didn't clearly specify GL_TEXTURE_COORD_ARRAY works with glGetVertexArrayIntegeri_vEXT)

Number

    353

Dependencies

    This extension is written against the OpenGL 2.1 specification.

    This extension interacts with the matrix manipulation commands
    introduced by OpenGL 1.0.

    This extension interacts with the texture object manipulation commands
    introduced by EXT_texture_object and standardized by OpenGL 1.1.

    This extension interacts with the 3D texture object manipulation
    commands introduced by EXT_texture3D and standardized by OpenGL 1.2.

    This extension interacts with the multitexture command introduced
    by ARB_multitexture and standardized by OpenGL 1.2.1.

    This extension interacts with the matrix transpose manipulation
    commands introduced by ARB_transpose_matrix and standardized by
    OpenGL 1.3.

    This extension interacts with the local parameter program object
    manipulation commands introduced by ARB_vertex_program.

    This extension interacts with the texture rectangle enable and target
    binding introduced by ARB_texture_rectangle (and NV_texture_rectangle
    and EXT_texture_rectangle).

    This extension interacts with the buffer manipulation commands
    standardized by OpenGL 1.5.

    This extension interacts with the GLSL uniform commands standardized
    by OpenGL 2.0.

    This extension interacts with the GLSL uniform matrix commands
    standardized by OpenGL 2.1.

    This extension interacts with the framebuffer object commands
    introduced by EXT_framebuffer_object and standardized by OpenGL 3.0.

    This extension interacts with the framebuffer blit commands introduced
    by EXT_framebuffer_blit and standardized by OpenGL 3.0.

    This extension interacts with the framebuffer multisample commands
    introduced by EXT_framebuffer_multisample and standardized by
    OpenGL 3.0.

    This extension interacts with the vertex array object commands
    introduced by APPLE_vertex_array_object and standardized by
    OpenGL 3.0.

    This extension interacts with the integer texture parameter commands
    introduced by EXT_texture_integer and standardized by OpenGL 3.0.

    This extension interacts with the texture buffer commands introduced
    by EXT_texture_buffer_object.

    This extension interacts with the GLSL integer uniform commands
    introduced by EXT_gpu_shader4.

    This extension interacts with the local plural parameter program
    object manipulation commands introduced by EXT_gpu_program_parameters.

    This extension interacts with the local integer parameter program
    object manipulation commands introduced by NV_gpu_program4.

    This extension trivially interacts with the EnableIndexedEXT
    and DisableIndexed commands and the integer and boolean indexed
    queries introduced by EXT_draw_buffers2, EXT_transform_feedback,
    and NV_transform_feedback.

    This extension interacts with NV_explicit_multisample.

    This extension trivially interacts with EXT_texture_array.

    This extension trivially interacts with NV_texture_cube_map_array.

    This extension interacts with the buffer data copying command
    introduced by  EXT_copy_buffer and standardized by OpenGL 3.0.

Overview

    This extension introduces a set of new "direct state access"
    commands (meaning no selector is involved) to access (update and
    query) OpenGL state that previously depended on the OpenGL state
    selectors for access.  These new commands supplement the existing
    selector-based OpenGL commands to access the same state.

    The intent of this extension is to make it more efficient for
    libraries to avoid disturbing selector and latched state.  The
    extension also allows more efficient command usage by eliminating
    the need for selector update commands.

    Two derivative advantages of this extension are 1) display lists
    can be executed using these commands that avoid disturbing selectors
    that subsequent commands may depend on, and 2) drivers implemented
    with a dual-thread partitioning with OpenGL command buffering from
    an application thread and then OpenGL command dispatching in a
    concurrent driver thread can avoid thread synchronization created by
    selector saving, setting, command execution, and selector restoration.

    This extension does not itself add any new OpenGL state.

    We call a state variable in OpenGL an "OpenGL state selector" or
    simply a "selector" if OpenGL commands depend on the state variable
    to determine what state to query or update.  The matrix mode and
    active texture are both selectors.  Object bindings for buffers,
    programs, textures, and framebuffer objects are also selectors.

    We call OpenGL state "latched" if the state is set by one OpenGL
    command but then that state is saved by a subsequent command or the
    state determines how client memory or buffer object memory is accessed
    by a subsequent command.  The array and element array buffer bindings
    are latched by vertex array specification commands to determine
    which buffer a given vertex array uses.  Vertex array state and pixel
    pack/unpack state decides how client memory or buffer object memory is
    accessed by subsequent vertex pulling or image specification commands.

    The existence of selectors and latched state in the OpenGL API
    reduces the number of parameters to various sets of OpenGL commands
    but complicates the access to state for layered libraries which seek
    to access state without disturbing other state, namely the state of
    state selectors and latched state.  In many cases, selectors and
    latched state were introduced by extensions as OpenGL evolved to
    minimize the disruption to the OpenGL API when new functionality,
    particularly the pluralization of existing functionality as when
    texture objects and later multiple texture units, was introduced.

    The OpenGL API involves several selectors (listed in historical
    order of introduction):

      o  The matrix mode.

      o  The current bound texture for each supported texture target.

      o  The active texture.

      o  The active client texture.

      o  The current bound program for each supported program target.

      o  The current bound buffer for each supported buffer target.

      o  The current GLSL program.

      o  The current framebuffer object.

    The new selector-free update commands can be compiled into display
    lists.

    The OpenGL API has latched state for vertex array buffer objects
    and pixel store state.  When an application issues a GL command to
    unpack or pack pixels (for example, glTexImage2D or glReadPixels
    respectively), the current unpack and pack pixel store state
    determines how the pixels are unpacked from/packed to client memory
    or pixel buffer objects.  For example, consider:

      glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE);
      glPixelStorei(GL_UNPACK_ROW_LENGTH, 640);
      glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 47);
      glDrawPixels(100, 100, GL_RGB, GL_FLOAT, pixels);

    The unpack swap bytes and row length state set by the preceding
    glPixelStorei commands (as well as the 6 other unpack pixel store
    state variables) control how data is read (unpacked) from buffer of
    data pointed to by pixels.  The glBindBuffer command also specifies
    an unpack buffer object (47) so the pixel pointer is actually treated
    as a byte offset into buffer object 47.

    When an application issues a command to configure a vertex array,
    the current array buffer state is latched as the binding for the
    particular vertex array being specified.  For example, consider:

      glBindBuffer(GL_ARRAY_BUFFER, 23);
      glVertexPointer(3, GL_FLOAT, 12, pointer);

    The glBindBuffer command updates the array buffering binding
    (GL_ARRAY_BUFFER_BINDING) to the buffer object named 23.  The
    subsequent glVertexPointer command specifies explicit parameters
    for the size, type, stride, and pointer to access the position
    vertex array BUT ALSO latches the current array buffer binding for
    the vertex array buffer binding (GL_VERTEX_ARRAY_BUFFER_BINDING).
    Effectively the current array buffer binding buffer object becomes
    an implicit fifth parameter to glVertexPointer and this applies to
    all the gl*Pointer vertex array specification commands.

    Selectors and latched state create problems for layered libraries
    using OpenGL because selectors require the selector state to be
    modified to update some other state and latched state means implicit
    state can affect the operation of commands specifying, packing, or
    unpacking data through pointers/offsets.  For layered libraries,
    a state update performed by the library may attempt to save the
    selector state, set the selector, update/query some state the
    selector controls, and then restore the selector to its saved state.
    Layered libraries can skip the selector save/restore but this risks
    introducing uncertainty about the state of a selector after calling
    layered library routines.  Such selector side-effects are difficult
    to document and lead to compatibility issues as the layered library
    evolves or its usage varies.  For latched state, layered libraries
    may find commands such as glDrawPixels do not work as expected
    because latched pixel store state is not what the library expects.
    Querying or pushing the latched state, setting the latched state
    explicitly, performing the operation involving latched state, and
    then restoring or popping the latched state avoids entanglements
    with latched state but at considerable cost.

    EXAMPLE USAGE OF THIS EXTENSION'S FUNCTIONALITY

    Consider the following routine to set the modelview matrix involving
    the matrix mode selector:

      void setModelviewMatrix(const GLfloat matrix[16])
      {
        GLenum savedMatrixMode;

        glGetIntegerv(GL_MATRIX_MODE, &savedMatrixMode);
        glMatrixMode(GL_MODELVIEW);
        glLoadMatrixf(matrix);
        glMatrixMode(savedMatrixMode);
      }

    Notice that four OpenGL commands are required to update the current
    modelview matrix without disturbing the matrix mode selector.

    OpenGL query commands can also substantially reduce the performance
    of modern OpenGL implementations which may off-load OpenGL state
    processing to another CPU core/thread or to the GPU itself.

    An alternative to querying the selector is to use the
    glPushAttrib/glPopAttrib commands.  However this approach typically
    involves pushing far more state than simply the one or two selectors
    that need to be saved and restored.  Because so much state is
    associated with a given push/pop attribute bit, the glPushAttrib
    and glPopAttrib commands are considerably more costly than the
    save/restore approach.  Additionally glPushAttrib risks overflowing
    the attribute stack.

    The reliability and performance of layered libraries and applications
    can be improved by adding to the OpenGL API a new set of commands
    to access directly OpenGL state that otherwise involves selectors
    to access.

    The above example can be reimplemented more efficiently and without
    selector side-effects:

      void setModelviewMatrix(const GLfloat matrix[16])
      {
        glMatrixLoadfEXT(GL_MODELVIEW, matrix);
      }

    Consider a layered library seeking to load a texture:

      void loadTexture(GLint texobj, GLint width, GLint height,
                       void *data)
      {
        glBindTexture(GL_TEXTURE_2D, texobj);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8,
                     width, height, GL_RGB, GL_FLOAT, data);
      }

    The library expects the data to be packed into the buffer pointed
    to by data.  But what if the current pixel unpack buffer binding
    is not zero so the current pixel unpack buffer, rather than client
    memory, will be read?  Or what if the application has modified
    the GL_UNPACK_ROW_LENGTH pixel store state before loadTexture
    is called?  

    We can fix the routine by calling glBindBuffer(GL_PIXEL_UNPACK_BUFFER,
    0) and setting all the pixel store unpack state to the initial state
    the loadTexture routine expects, but this is expensive.  It also risks
    disturbing the state so when loadTexture returns to the application,
    the application doesn't realize the current texture object (for
    whatever texture unit the current active texture happens to be) and
    pixel store state has changed.

    We can more efficiently implement this routine without disturbing
    selector or latched state as follows:

      void loadTexture(GLint texobj, GLint width, GLint height,
                       void *data)
      {
        glPushClientAttribDefaultEXT(GL_CLIENT_PIXEL_STORE_BIT);
        glTextureImage2D(texobj, GL_TEXTURE_2D, 0, GL_RGB8,
                         width, height, GL_RGB, GL_FLOAT, data);
        glPopClientAttrib();
      }

    Now loadTexture does not have to worry about inappropriately
    configured pixel store state or a non-zero pixel unpack buffer
    binding.  And loadTexture has no unintended side-effects for
    selector or latched state (assuming the client attrib state does
    not overflow).

New Procedures and Functions

    <OpenGL 1.1: New client commands>

        void ClientAttribDefaultEXT(bitfield mask);
        void PushClientAttribDefaultEXT(bitfield mask);

    <OpenGL 1.0: New matrix commands add "Matrix" prefix to name,
    drops "Matrix" suffix from name, and add initial "enum matrixMode"
    parameter>

        void MatrixLoadfEXT(enum matrixMode, const float *m);
        void MatrixLoaddEXT(enum matrixMode, const double *m);

        void MatrixMultfEXT(enum matrixMode, const float *m);
        void MatrixMultdEXT(enum matrixMode, const double *m);

        void MatrixLoadIdentityEXT(enum matrixMode);

        void MatrixRotatefEXT(enum matrixMode, float angle,
                              float x, float y, float z);
        void MatrixRotatedEXT(enum matrixMode, double angle,
                              double x, double y, double z);

        void MatrixScalefEXT(enum matrixMode,
                             float x, float y, float z);
        void MatrixScaledEXT(enum matrixMode,
                             double x, double y, double z);

        void MatrixTranslatefEXT(enum matrixMode,
                                 float x, float y, float z);
        void MatrixTranslatedEXT(enum matrixMode,
                                 double x, double y, double z);

        void MatrixOrthoEXT(enum matrixMode, double l, double r,
                            double b, double t, double n, double f);
        void MatrixFrustumEXT(enum matrixMode, double l, double r,
                              double b, double t, double n, double f);

        void MatrixPushEXT(enum matrixMode);
        void MatrixPopEXT(enum matrixMode);

    <OpenGL 1.1: New texture object commands and queries replace "Tex"
    in name with "Texture" and add initial "uint texture" parameter>

        void TextureParameteriEXT(uint texture, enum target,
                                  enum pname, int param);
        void TextureParameterivEXT(uint texture, enum target,
                                   enum pname, const int *param);

        void TextureParameterfEXT(uint texture, enum target,
                                  enum pname, float param);
        void TextureParameterfvEXT(uint texture, enum target,
                                   enum pname, const float *param);

        void TextureImage1DEXT(uint texture, enum target,
                               int level, int internalformat,
                               sizei width, int border,
                               enum format, enum type, const void *pixels);
        void TextureImage2DEXT(uint texture, enum target,
                               int level, int internalformat,
                               sizei width, sizei height, int border,
                               enum format, enum type, const void *pixels);

        void TextureSubImage1DEXT(uint texture, enum target,
                                  int level, int xoffset, sizei width,
                                  enum format, enum type,
                                  const void *pixels);
        void TextureSubImage2DEXT(uint texture, enum target,
                                  int level, int xoffset, int yoffset,
                                  sizei width, sizei height,
                                  enum format, enum type,
                                  const void *pixels);

        void CopyTextureImage1DEXT(uint texture, enum target,
                                   int level, enum internalformat,
                                   int x, int y, sizei width, int border);
        void CopyTextureImage2DEXT(uint texture, enum target,
                                   int level, enum internalformat,
                                   int x, int y,
                                   sizei width, sizei height, int border);

        void CopyTextureSubImage1DEXT(uint texture, enum target,
                                      int level, int xoffset,
                                      int x, int y, sizei width);
        void CopyTextureSubImage2DEXT(uint texture, enum target,
                                      int level, int xoffset, int yoffset,
                                      int x, int y,
                                      sizei width, sizei height);

        void GetTextureImageEXT(uint texture, enum target,
                                int level,
                                enum format, enum type, void *pixels);

        void GetTextureParameterfvEXT(uint texture, enum target,
                                      enum pname, float *params);
        void GetTextureParameterivEXT(uint texture, enum target,
                                      enum pname, int *params);

        void GetTextureLevelParameterfvEXT(uint texture, enum target,
                                           int level,
                                           enum pname, float *params);
        void GetTextureLevelParameterivEXT(uint texture, enum target,
                                           int level,
                                           enum pname, int *params);

    <OpenGL 1.2: New 3D texture object commands replace "Tex" in name with
    "Texture" and adds initial "uint texture" parameter>

        void TextureImage3DEXT(uint texture, enum target,
                               int level, int internalformat,
                               sizei width, sizei height, sizei depth,
                               int border,
                               enum format, enum type, const void *pixels);

        void TextureSubImage3DEXT(uint texture, enum target,
                                  int level,
                                  int xoffset, int yoffset, int zoffset,
                                  sizei width, sizei height, sizei depth,
                                  enum format, enum type,
                                  const void *pixels);
        void CopyTextureSubImage3DEXT(uint texture, enum target,
                                      int level,
                                      int xoffset, int yoffset, int zoffset,
                                      int x, int y,
                                      sizei width, sizei height);

    <OpenGL 1.2.1: New multitexture commands and queries prefix "Multi"
    before "Tex" and add an initial "enum texunit" parameter (to identify
    the texture unit).>

        void BindMultiTextureEXT(enum texunit, enum target, uint texture);

        void MultiTexCoordPointerEXT(enum texunit, int size, enum type,
                                     sizei stride, const void *pointer);

        void MultiTexEnvfEXT(enum texunit, enum target, enum pname,
                             float param);
        void MultiTexEnvfvEXT(enum texunit, enum target, enum pname,
                              const float *params);
        void MultiTexEnviEXT(enum texunit, enum target, enum pname,
                             int param);
        void MultiTexEnvivEXT(enum texunit, enum target, enum pname,
                              const int *params);

        void MultiTexGendEXT(enum texunit, enum coord, enum pname,
                             double param);
        void MultiTexGendvEXT(enum texunit, enum coord, enum pname,
                              const double *params);
        void MultiTexGenfEXT(enum texunit, enum coord, enum pname,
                             float param);
        void MultiTexGenfvEXT(enum texunit, enum coord, enum pname,
                              const float *params);
        void MultiTexGeniEXT(enum texunit, enum coord, enum pname,
                             int param);
        void MultiTexGenivEXT(enum texunit, enum coord, enum pname,
                              const int *params);

        void GetMultiTexEnvfvEXT(enum texunit, enum target, enum pname,
                                 float *params);
        void GetMultiTexEnvivEXT(enum texunit, enum target, enum pname,
                                 int *params);

        void GetMultiTexGendvEXT(enum texunit, enum coord, enum pname,
                                 double *params);
        void GetMultiTexGenfvEXT(enum texunit, enum coord, enum pname,
                                 float *params);
        void GetMultiTexGenivEXT(enum texunit, enum coord, enum pname,
                                 int *params);

        void MultiTexParameteriEXT(enum texunit, enum target,
                                   enum pname, int param);
        void MultiTexParameterivEXT(enum texunit, enum target,
                                    enum pname, const int *param);

        void MultiTexParameterfEXT(enum texunit, enum target,
                                   enum pname, float param);
        void MultiTexParameterfvEXT(enum texunit, enum target,
                                    enum pname, const float *param);

        void MultiTexImage1DEXT(enum texunit, enum target,
                                int level, int internalformat,
                                sizei width, int border,
                                enum format, enum type, const void *pixels);
        void MultiTexImage2DEXT(enum texunit, enum target,
                                int level, int internalformat,
                                sizei width, sizei height, int border,
                                enum format, enum type, const void *pixels);

        void MultiTexSubImage1DEXT(enum texunit, enum target,
                                   int level, int xoffset, sizei width,
                                   enum format, enum type,
                                   const void *pixels);
        void MultiTexSubImage2DEXT(enum texunit, enum target,
                                   int level, int xoffset, int yoffset,
                                   sizei width, sizei height,
                                   enum format, enum type,
                                   const void *pixels);

        void CopyMultiTexImage1DEXT(enum texunit, enum target,
                                    int level, enum internalformat,
                                    int x, int y, sizei width, int border);
        void CopyMultiTexImage2DEXT(enum texunit, enum target,
                                    int level, enum internalformat,
                                    int x, int y,
                                    sizei width, sizei height, int border);

        void CopyMultiTexSubImage1DEXT(enum texunit, enum target,
                                       int level, int xoffset,
                                       int x, int y, sizei width);
        void CopyMultiTexSubImage2DEXT(enum texunit, enum target,
                                       int level, int xoffset, int yoffset,
                                       int x, int y,
                                       sizei width, sizei height);

        void GetMultiTexImageEXT(enum texunit, enum target,
                                 int level,
                                 enum format, enum type, void *pixels);

        void GetMultiTexParameterfvEXT(enum texunit, enum target,
                                       enum pname, float *params);
        void GetMultiTexParameterivEXT(enum texunit, enum target,
                                       enum pname, int *params);

        void GetMultiTexLevelParameterfvEXT(enum texunit, enum target,
                                            int level,
                                            enum pname, float *params);
        void GetMultiTexLevelParameterivEXT(enum texunit, enum target,
                                            int level,
                                            enum pname, int *params);

        void MultiTexImage3DEXT(enum texunit, enum target,
                                int level, int internalformat,
                                sizei width, sizei height, sizei depth,
                                int border,
                                enum format, enum type, const void *pixels);

        void MultiTexSubImage3DEXT(enum texunit, enum target,
                                   int level,
                                   int xoffset, int yoffset, int zoffset,
                                   sizei width, sizei height, sizei depth,
                                   enum format, enum type,
                                   const void *pixels);
        void CopyMultiTexSubImage3DEXT(enum texunit, enum target,
                                       int level,
                                       int xoffset, int yoffset, int zoffset,
                                       int x, int y,
                                       sizei width, sizei height);

    <OpenGL 1.2.1: New indexed texture commands and queries append
    "Indexed" to name and add "uint index" parameter (to identify the
    texture unit index) after state name parameters (if any) and before
    state value parameters>

        void EnableClientStateIndexedEXT(enum array, uint index);
        void DisableClientStateIndexedEXT(enum array, uint index);

    <OpenGL 3.0: New indexed texture commands and queries append "i"
    to name and add "uint index" parameter (to identify the texture
    unit index) after state name parameters (if any) and before state
    value parameters>

        void EnableClientStateiEXT(enum array, uint index);
        void DisableClientStateiEXT(enum array, uint index);

    <OpenGL 1.2.1: New indexed generic queries (added for indexed texture
    state) append "Indexed" to name and add "uint index" parameter
    (to identify the texture unit) after state name parameters (if any) and
    before state value parameters>

        void GetFloatIndexedvEXT(enum target, uint index, float *params);
        void GetDoubleIndexedvEXT(enum target, uint index, double *params);

        void GetPointerIndexedvEXT(enum target, uint index, void **params);

    <OpenGL 3.0: New indexed generic queries (added for indexed texture
    state) replace "v" for "i_v" to name and add "uint index" parameter
    (to identify the texture unit) after state name parameters (if any)
    and before state value parameters>

        void GetFloati_vEXT(enum pname, uint index, float *params);
        void GetDoublei_vEXT(enum pname, uint index, double *params);

        void GetPointeri_vEXT(enum pname, uint index, void **params);

    <OpenGL 1.2.1:  Extend the functionality of these EXT_draw_buffers2
    commands and queries for multitexture>

        void EnableIndexedEXT(enum cap, uint index);
        void DisableIndexedEXT(enum cap, uint index);

        boolean IsEnabledIndexedEXT(enum target, uint index);

        void GetIntegerIndexedvEXT(enum target, uint index, int *params);
        void GetBooleanIndexedvEXT(enum target, uint index,
                                   boolean *params);

    <ARB_vertex_program: New program commands and queries add "Named"
    prefix to name and adds initial "uint program" parameter>

        void NamedProgramStringEXT(uint program, enum target, enum format,
                                   sizei len, const void *string); 

        void NamedProgramLocalParameter4dEXT(uint program, enum target,
                                             uint index,
                                             double x, double y,
                                             double z, double w);
        void NamedProgramLocalParameter4dvEXT(uint program, enum target,
                                              uint index,
                                              const double *params);
        void NamedProgramLocalParameter4fEXT(uint program, enum target,
                                             uint index,
                                             float x, float y,
                                             float z, float w);
        void NamedProgramLocalParameter4fvEXT(uint program, enum target,
                                              uint index,
                                              const float *params);

        void GetNamedProgramLocalParameterdvEXT(uint program, enum target,
                                                uint index,
                                                double *params);
        void GetNamedProgramLocalParameterfvEXT(uint program, enum target,
                                                uint index,
                                                float *params);
        void GetNamedProgramivEXT(uint program, enum target,
                                  enum pname, int *params);
        void GetNamedProgramStringEXT(uint program, enum target,
                                      enum pname, void *string);

    <OpenGL 1.3: New compressed texture object commands replace "Tex"
    in name with "Texture" and add initial "uint texture" parameter>

        void CompressedTextureImage3DEXT(uint texture, enum target, int level,
                                         enum internalformat,
                                         sizei width, sizei height,
                                         sizei depth, int border,
                                         sizei imageSize, const void *data);
        void CompressedTextureImage2DEXT(uint texture, enum target, int level,
                                         enum internalformat,
                                         sizei width, sizei height,
                                         int border, sizei imageSize,
                                         const void *data);
        void CompressedTextureImage1DEXT(uint texture, enum target, int level,
                                         enum internalformat,
                                         sizei width, int border,
                                         sizei imageSize, const void *data);
        void CompressedTextureSubImage3DEXT(uint texture, enum target, int level,
                                            int xoffset, int yoffset,
                                            int zoffset,
                                            sizei width, sizei height,
                                            sizei depth, enum format,
                                            sizei imageSize, const void *data);
        void CompressedTextureSubImage2DEXT(uint texture, enum target, int level,
                                            int xoffset, int yoffset,
                                            sizei width, sizei height,
                                            enum format,
                                            sizei imageSize, const void *data);
        void CompressedTextureSubImage1DEXT(uint texture, enum target, int level,
                                            int xoffset, sizei width,
                                            enum format,
                                            sizei imageSize, const void *data);

        void GetCompressedTextureImageEXT(uint texture, enum target,
                                          int level, void *img);

    <OpenGL 1.3: New multitexture compressed texture commands and queries
    prefix "Multi" before "Tex" and add an initial "enum texunit"
    parameter (to identify the texture unit).>

        void CompressedMultiTexImage3DEXT(enum texunit, enum target, int level,
                                          enum internalformat,
                                          sizei width, sizei height,
                                          sizei depth, int border,
                                          sizei imageSize, const void *data);
        void CompressedMultiTexImage2DEXT(enum texunit, enum target, int level,
                                          enum internalformat,
                                          sizei width, sizei height,
                                          int border, sizei imageSize,
                                          const void *data);
        void CompressedMultiTexImage1DEXT(enum texunit, enum target, int level,
                                          enum internalformat,
                                          sizei width, int border,
                                          sizei imageSize, const void *data);
        void CompressedMultiTexSubImage3DEXT(enum texunit, enum target, int level,
                                             int xoffset, int yoffset,
                                             int zoffset,
                                             sizei width, sizei height,
                                             sizei depth, enum format,
                                             sizei imageSize, const void *data);
        void CompressedMultiTexSubImage2DEXT(enum texunit, enum target, int level,
                                             int xoffset, int yoffset,
                                             sizei width, sizei height,
                                             enum format,
                                             sizei imageSize, const void *data);
        void CompressedMultiTexSubImage1DEXT(enum texunit, enum target, int level,
                                             int xoffset, sizei width,
                                             enum format,
                                             sizei imageSize, const void *data);

        void GetCompressedMultiTexImageEXT(enum texunit, enum target,
                                           int level, void *img);

    <OpenGL 1.3: New transpose matrix commands add "Matrix" suffix
    to name, drops "Matrix" suffix from name, and add initial "enum
    matrixMode" parameter>

        void MatrixLoadTransposefEXT(enum matrixMode, const float *m);
        void MatrixLoadTransposedEXT(enum matrixMode, const double *m);

        void MatrixMultTransposefEXT(enum matrixMode, const float *m);
        void MatrixMultTransposedEXT(enum matrixMode, const double *m);

    <OpenGL 1.5: New buffer commands and queries replace "Buffer" with
    "NamedBuffer" in name and replace "enum target" parameter with
    "uint buffer">

        void NamedBufferDataEXT(uint buffer, sizeiptr size,
                                const void *data, enum usage);
        void NamedBufferSubDataEXT(uint buffer, intptr offset,
                                   sizeiptr size, const void *data);
        void* MapNamedBufferEXT(uint buffer, enum access);
        boolean UnmapNamedBufferEXT(uint buffer);
        void GetNamedBufferParameterivEXT(uint buffer,
                                          enum pname, int *params);
        void GetNamedBufferPointervEXT(uint buffer,
                                       enum pname, void* *params);
        void GetNamedBufferSubDataEXT(uint buffer,
                                      intptr offset, sizeiptr size, void *data);

    <OpenGL 2.0: New uniform commands add "Program" prefix to name and
    add initial "uint program" parameter>

        void ProgramUniform1fEXT(uint program, int location, float v0);
        void ProgramUniform2fEXT(uint program, int location,
                                 float v0, float v1);
        void ProgramUniform3fEXT(uint program, int location,
                                 float v0, float v1, float v2);
        void ProgramUniform4fEXT(uint program, int location,
                                 float v0, float v1, float v2, float v3);

        void ProgramUniform1iEXT(uint program, int location, int v0);
        void ProgramUniform2iEXT(uint program, int location,
                                 int v0, int v1);
        void ProgramUniform3iEXT(uint program, int location,
                                 int v0, int v1, int v2);
        void ProgramUniform4iEXT(uint program, int location,
                                 int v0, int v1, int v2, int v3);

        void ProgramUniform1fvEXT(uint program, int location,
                                  sizei count, const float *value);
        void ProgramUniform2fvEXT(uint program, int location,
                                  sizei count, const float *value);
        void ProgramUniform3fvEXT(uint program, int location,
                                  sizei count, const float *value);
        void ProgramUniform4fvEXT(uint program, int location,
                                  sizei count, const float *value);

        void ProgramUniform1ivEXT(uint program, int location,
                                  sizei count, const int *value);
        void ProgramUniform2ivEXT(uint program, int location,
                                  sizei count, const int *value);
        void ProgramUniform3ivEXT(uint program, int location,
                                  sizei count, const int *value);
        void ProgramUniform4ivEXT(uint program, int location,
                                  sizei count, const int *value);

        void ProgramUniformMatrix2fvEXT(uint program, int location,
                                        sizei count, boolean transpose,
                                        const float *value);
        void ProgramUniformMatrix3fvEXT(uint program, int location,
                                        sizei count, boolean transpose,
                                        const float *value);
        void ProgramUniformMatrix4fvEXT(uint program, int location,
                                        sizei count, boolean transpose,
                                        const float *value);

    <OpenGL 2.1: New uniform matrix commands add "Program" prefix to
    name and add initial "uint program" parameter>

        void ProgramUniformMatrix2x3fvEXT(uint program, int location,
                                          sizei count, boolean transpose,
                                          const float *value);
        void ProgramUniformMatrix3x2fvEXT(uint program, int location,
                                          sizei count, boolean transpose,
                                          const float *value);
        void ProgramUniformMatrix2x4fvEXT(uint program, int location,
                                          sizei count, boolean transpose,
                                          const float *value);
        void ProgramUniformMatrix4x2fvEXT(uint program, int location,
                                          sizei count, boolean transpose,
                                          const float *value);
        void ProgramUniformMatrix3x4fvEXT(uint program, int location,
                                          sizei count, boolean transpose,
                                          const float *value);
        void ProgramUniformMatrix4x3fvEXT(uint program, int location,
                                          sizei count, boolean transpose,
                                          const float *value);

    <EXT_texture_buffer_object:  New texture buffer object command
    replaces "Tex" in name with "Texture" and adds initial "uint texture"
    parameter>

        void TextureBufferEXT(uint texture, enum target,
                              enum internalformat, uint buffer);

    <EXT_texture_buffer_object: New multitexture texture buffer command
    prefixes "Multi" before "Tex" and add an initial "enum texunit"
    parameter (to identify the texture unit).>

        void MultiTexBufferEXT(enum texunit, enum target,
                               enum internalformat, uint buffer);

    <EXT_texture_integer: New integer texture object commands and queries
    replace "Tex" in name with "Texture" and add initial "uint texture"
    parameter>

        void TextureParameterIivEXT(uint texture, enum target,
                                    enum pname, const int *params);
        void TextureParameterIuivEXT(uint texture, enum target,
                                     enum pname, const uint *params);

        void GetTextureParameterIivEXT(uint texture, enum target,
                                       enum pname, int *params);
        void GetTextureParameterIuivEXT(uint texture, enum target,
                                        enum pname, uint *params);

    <EXT_texture_integer: New multitexture integer texture commands and
    queries prefix "Multi" before "Tex" and add an initial "enum texunit"
    parameter (to identify the texture unit).>

        void MultiTexParameterIivEXT(enum texunit, enum target,
                                     enum pname, const int *params);
        void MultiTexParameterIuivEXT(enum texunit, enum target,
                                      enum pname, const uint *params);

        void GetMultiTexParameterIivEXT(enum texunit, enum target,
                                        enum pname, int *params);
        void GetMultiTexParameterIuivEXT(enum texunit, enum target,
                                         enum pname, uint *params);

    <EXT_gpu_shader4: New integer uniform commands add "Program" prefix
    to name and add initial "uint program" parameter>

        void ProgramUniform1uiEXT(uint program, int location, uint v0);
        void ProgramUniform2uiEXT(uint program, int location,
                                  uint v0, uint v1);
        void ProgramUniform3uiEXT(uint program, int location,
                                  uint v0, uint v1, uint v2);
        void ProgramUniform4uiEXT(uint program, int location,
                                  uint v0, uint v1, uint v2, uint v3);

        void ProgramUniform1uivEXT(uint program, int location,
                                   sizei count, const uint *value);
        void ProgramUniform2uivEXT(uint program, int location,
                                   sizei count, const uint *value);
        void ProgramUniform3uivEXT(uint program, int location,
                                   sizei count, const uint *value);
        void ProgramUniform4uivEXT(uint program, int location,
                                   sizei count, const uint *value);

    <EXT_gpu_program_parameters: New program command adds "Named" prefix
    to name and adds "uint program" parameter>

        void NamedProgramLocalParameters4fvEXT(uint program, enum target,
                                               uint index, sizei count,
                                               const float *params); 

    <NV_gpu_program4: New program commands and queries add "Named"
    prefix to name and replace "enum target" with "uint program">

        void NamedProgramLocalParameterI4iEXT(uint program, enum target,
                                              uint index, 
                                              int x, int y,
                                              int z, int w);
        void NamedProgramLocalParameterI4ivEXT(uint program, enum target,
                                               uint index, 
                                               const int *params);
        void NamedProgramLocalParametersI4ivEXT(uint program, enum target,
                                                uint index, sizei count,
                                                const int *params);
        void NamedProgramLocalParameterI4uiEXT(uint program, enum target,
                                               uint index, 
                                               uint x, uint y,
                                               uint z, uint w);
        void NamedProgramLocalParameterI4uivEXT(uint program, enum target,
                                                uint index, 
                                                const uint *params);
        void NamedProgramLocalParametersI4uivEXT(uint program, enum target,
                                                 uint index, sizei count,
                                                 const uint *params);

        void GetNamedProgramLocalParameterIivEXT(uint program, enum target,
                                                 uint index,
                                                 int *params);
        void GetNamedProgramLocalParameterIuivEXT(uint program, enum target,
                                                  uint index,
                                                  uint *params);

    <OpenGL 3.0: New renderbuffer commands add "Named" prefix to name
    and replace "enum target" with "uint renderbuffer">

        void NamedRenderbufferStorageEXT(uint renderbuffer,
                                         enum internalformat,
                                         sizei width, sizei height);

        void GetNamedRenderbufferParameterivEXT(uint renderbuffer,
                                                enum pname, int *params);

    <OpenGL 3.0: New renderbuffer commands add "Named"
    prefix to name and replace "enum target" with "uint renderbuffer">

        void NamedRenderbufferStorageMultisampleEXT(uint renderbuffer,
                                                    sizei samples,
                                                    enum internalformat,
                                                    sizei width, sizei height);

    <NV_framebuffer_multisample_coverage: New renderbuffer commands
    add "Named" prefix to name and replace "enum target" with "uint
    renderbuffer">

        void NamedRenderbufferStorageMultisampleCoverageEXT(uint renderbuffer,
                                                            sizei coverageSamples, 
                                                            sizei colorSamples,
                                                            enum internalformat,
                                                            sizei width,
                                                            sizei height);

    <OpenGL 3.0: New framebuffer commands add "Named" prefix to name
    and replace "enum target" with "uint framebuffer">

        enum CheckNamedFramebufferStatusEXT(uint framebuffer,
                                            enum target);

        void NamedFramebufferTexture1DEXT(uint framebuffer,
                                          enum attachment,
                                          enum textarget, uint texture,
                                          int level);
        void NamedFramebufferTexture2DEXT(uint framebuffer,
                                          enum attachment,
                                          enum textarget, uint texture,
                                          int level);
        void NamedFramebufferTexture3DEXT(uint framebuffer,
                                          enum attachment,
                                          enum textarget, uint texture,
                                          int level, int zoffset);

        void NamedFramebufferRenderbufferEXT(uint framebuffer,
                                             enum attachment,
                                             enum renderbuffertarget,
                                             uint renderbuffer);

        void GetNamedFramebufferAttachmentParameterivEXT(uint framebuffer,
                                                         enum attachment,
                                                         enum pname,
                                                         int *params);

    <OpenGL 3.0: New texture commands add "Texture" within name and
    replace "enum target" with "uint texture">

        void GenerateTextureMipmapEXT(uint texture, enum target);

    <OpenGL 3.0: New texture commands add "MultiTex" within name and
    replace "enum target" with "enum texunit">

        void GenerateMultiTexMipmapEXT(enum texunit, enum target);

    <OpenGL 3.0: New framebuffer commands>

        void FramebufferDrawBufferEXT(uint framebuffer, enum mode);
        void FramebufferDrawBuffersEXT(uint framebuffer, sizei n,
                                       const enum *bufs)
        void FramebufferReadBufferEXT(uint framebuffer, enum mode);

    <OpenGL 3.0: New framebuffer query>

        void GetFramebufferParameterivEXT(uint framebuffer, enum pname,
                                          int *param);

    <OpenGL 3.0: New buffer data copy command>
        void NamedCopyBufferSubDataEXT(uint readBuffer, uint writeBuffer, 
                                       intptr readOffset, intptr writeOffset,
                                       sizeiptr size);

    <EXT_geometry_shader4 or NV_gpu_program4: New framebuffer commands
    add "Named" prefix to name and replace "enum target" with "uint
    framebuffer">

        void NamedFramebufferTextureEXT(uint framebuffer, enum attachment, 
                                        uint texture, int level);
        void NamedFramebufferTextureLayerEXT(uint framebuffer,
                                             enum attachment, 
                                             uint texture,
                                             int level, int layer);
        void NamedFramebufferTextureFaceEXT(uint framebuffer, enum attachment,
                                            uint texture,
                                            int level, enum face);

    <NV_explicit_multisample:  New texture renderbuffer object command
    replaces "Tex" in name with "Texture" and add initial "uint texture"
    parameter> 

        void TextureRenderbufferEXT(uint texture, enum target,
                                    uint renderbuffer);

    <NV_explicit_multisample: New multitexture texture renderbuffer command
    prefixes "Multi" before "Tex" and add an initial "enum texunit"
    parameter (to identify the texture unit)>

        void MultiTexRenderbufferEXT(enum texunit, enum target,
                                     uint renderbuffer);

    <OpenGL 3.0: New vertex array specification commands for vertex
    array objects prefix "VertexArray", add initial "uint vaobj" and
    "uint buffer" parameters, change "Pointer" suffix to "Offset",
    and change the final parameter from "const void *" to "intptr offset">

        void VertexArrayVertexOffsetEXT(uint vaobj, uint buffer,
                                        int size, enum type, sizei stride,
                                        intptr offset);
        void VertexArrayColorOffsetEXT(uint vaobj, uint buffer,
                                       int size, enum type, sizei stride,
                                       intptr offset);
        void VertexArrayEdgeFlagOffsetEXT(uint vaobj, uint buffer,
                                          sizei stride, intptr offset);
        void VertexArrayIndexOffsetEXT(uint vaobj, uint buffer,
                                       enum type, sizei stride,
                                       intptr offset);
        void VertexArrayNormalOffsetEXT(uint vaobj, uint buffer,
                                        enum type, sizei stride,
                                        intptr offset);
        void VertexArrayTexCoordOffsetEXT(uint vaobj, uint buffer,
                                          int size, enum type, sizei stride,
                                          intptr offset);
        void VertexArrayMultiTexCoordOffsetEXT(uint vaobj, uint buffer,
                                               enum texunit,
                                               int size, enum type, sizei stride,
                                               intptr offset);
        void VertexArrayFogCoordOffsetEXT(uint vaobj, uint buffer,
                                          enum type, sizei stride,
                                          intptr offset);
        void VertexArraySecondaryColorOffsetEXT(uint vaobj, uint buffer,
                                                int size, enum type,
                                                sizei stride, intptr offset);
        void VertexArrayVertexAttribOffsetEXT(uint vaobj, uint buffer,
                                              uint index, int size,
                                              enum type, boolean normalized,
                                              sizei stride, intptr offset);
        void VertexArrayVertexAttribIOffsetEXT(uint vaobj, uint buffer,
                                               uint index, int size,
                                               enum type, sizei stride,
                                               intptr offset);

    <OpenGL 3.0: New vertex array enable commands for vertex array
    objects change "ClientState" to "VertexArray" and add an initial
    "uint vaobj" parameter>

        void EnableVertexArrayEXT(uint vaobj, enum array);
        void DisableVertexArrayEXT(uint vaobj, enum array);

    <OpenGL 3.0: New vertex attrib array enable commands for vertex
    array objects change "VertexAttribArray" to "VertexArrayAttrib"
    and add an initial "uint vaobj" parameter>

        void EnableVertexArrayAttribEXT(uint vaobj, uint index);
        void DisableVertexArrayAttribEXT(uint vaobj, uint index);

    <OpenGL 3.0: New queries for vertex array objects>

        void GetVertexArrayIntegervEXT(uint vaobj, enum pname,
                                       int *param);
        void GetVertexArrayPointervEXT(uint vaobj, enum pname,
                                       void **param);
        void GetVertexArrayIntegeri_vEXT(uint vaobj,
                                         uint index,
                                         enum pname,
                                         int *param);
        void GetVertexArrayPointeri_vEXT(uint vaobj,
                                         uint index,
                                         enum pname,
                                         void **param);

    <OpenGL 3.0: New buffer commands replace "Buffer" with "NamedBuffer"
    in name and replace "enum target" parameter with "uint buffer">

        void *MapNamedBufferRangeEXT(uint buffer, intptr offset,
                                     sizeiptr length, bitfield access);
        void FlushMappedNamedBufferRangeEXT(uint buffer, intptr offset,
                                            sizeiptr length);

New Tokens

    Accepted by the <pname> parameter of GetBooleanIndexedvEXT,
    GetIntegerIndexedvEXT, GetFloatIndexedvEXT, GetDoubleIndexedvEXT:
    GetBooleani_v, GetIntegeri_v, GetFloati_vEXT, GetDoublei_vEXT:

        PROGRAM_MATRIX_EXT                              0x8E2D
        TRANSPOSE_PROGRAM_MATRIX_EXT                    0x8E2E
        PROGRAM_MATRIX_STACK_DEPTH_EXT                  0x8E2F

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

    Insert the following after the 2nd sentence in the 4th paragraph in
    Section 2.5 (Errors):

    "Certain commands and queries provide direct state
    access to named objects (such as TextureParameteriEXT,
    NamedProgramLocalParameter4dEXT, NamedRenderbufferStorageEXT,
    NamedFramebufferTexture2DEXT, GetTextureImageEXT, etc.) and perform
    implicit object initialization when provided unused object names.
    When these commands and queries are given an object name not
    currently used, these commands and queries will first (prior to
    any further error checking) make the name used and appropriately
    initialize the named object to a new object state vector.  After this
    object initialization for unused names takes place, the command may
    subsequently generate an error.  In this case, the command's state
    update or query's result is ignored, but the name still becomes used
    and the object initialization still takes place."

    Add after the paragraph describing EnableClientState in Section 2.8
    (Vertex Arrays):

    "The following commands:

        void EnableClientStateIndexedEXT(enum array, uint index);
        void DisableClientStateIndexedEXT(enum array, uint index);
        void EnableClientStateiEXT(enum array, uint index);
        void DisableClientStateiEXT(enum array, uint index);

    are equivalent (assuming no errors) to the following:

        if (array == TEXTURE_COORD_ARRAY) {
          int savedClientActiveTexture;

          GetIntegerv(CLIENT_ACTIVE_TEXTURE, &savedClientActiveTexture);
          ClientActiveTexture(TEXTURE0+index);
          XXX(array);
          ClientActiveTexture(savedActiveTexture);
        } else {
          // Invalid enum
        }

    where index is the index parameter to the listed commands and XXX is
    the name of the command without its "Indexed" or "i" suffix (either
    EnableClientState or DisableClientState).  The error INVALID_VALUE
    is generated if index is greater or equal to the implementation's
    NUM_TEXTURE_COORDS value.  The error INVALID_ENUM is generated if
    array is not TEXTURE_COORD_ARRAY."

    Add before the last paragraph in Section 2.8 (Vertex Arrays):

    "The following command:

        void MultiTexCoordPointerEXT(enum texunit, int size, enum type,
                                     sizei stride, const void *pointer);

    is equivalent (assuming no errors) to the following:

        int savedClientActiveTexture;

        GetIntegerv(CLIENT_ACTIVE_TEXTURE, &savedClientActiveTexture);
        ClientActiveTexture(texunit);
        TexCoordPointer(...);
        ClientActiveTexture(savedActiveTexture);

    where ... is the list of the arguments for the command excluding
    the index parameter."

    Add to the end of section 2.9 (Buffer Objects), before section 2.9.1
    (Vertex Arrays in Buffer Objects):

    "The following commands:

        void NamedBufferDataEXT(uint buffer, sizeiptr size,
                                const void *data, enum usage);
        void NamedBufferSubDataEXT(uint buffer, intptr offset,
                                   sizeiptr size, const void *data);
        void* MapNamedBufferEXT(uint buffer, enum access);
        boolean UnmapNamedBufferEXT(uint buffer);
        void *MapNamedBufferRangeEXT(uint buffer, intptr offset,
                                     sizeiptr length, bitfield access);
        void FlushMappedNamedBufferRangeEXT(uint buffer, intptr offset,
                                            sizeiptr length);
        void NamedCopyBufferSubDataEXT(uint readBuffer, uint writeBuffer, 
                                       intptr readOffset, intptr writeOffset,
                                       sizeiptr size);

    operate identically to the corresponding command where "Named" is
    deleted from the name (and extension suffixes are dropped or updated
    appropriately) except, rather than updating the currently bound buffer
    for the buffer target parameter (a parameter not present for these
    listed commands), these "Named" commands update the buffer object
    named by the initial buffer parameter.  The remaining parameters
    following the initial buffer parameter for the listed "Named" commands
    match the parameters for the corresponding non-"Named" buffer command
    (except the target parameter is not needed because the buffer object
    to update is identified by its name) and are interpreted as they
    are for the non-"Named" buffer command.  If the buffer object named
    by the buffer parameter has not been previously bound or has been
    deleted since the last binding, the GL first creates a new state
    vector, initialized with a zero-sized memory buffer and comprising the
    state values listed in table 2.6.  There is no buffer corresponding
    to the name zero, these commands generate the INVALID_OPERATION
    error if the buffer parameter is zero."

    Add to the end of Section 2.10 (Vertex Array Objects):

    "The following commands:

        void VertexArrayVertexOffsetEXT(uint vaobj, uint buffer,
                                        int size, enum type, sizei stride,
                                        intptr offset);
        void VertexArrayColorOffsetEXT(uint vaobj, uint buffer,
                                       int size, enum type, sizei stride,
                                       intptr offset);
        void VertexArrayEdgeFlagOffsetEXT(uint vaobj, uint buffer,
                                          sizei stride, intptr offset);
        void VertexArrayIndexOffsetEXT(uint vaobj, uint buffer,
                                       enum type, sizei stride,
                                       intptr offset);
        void VertexArrayNormalOffsetEXT(uint vaobj, uint buffer,
                                        enum type, sizei stride,
                                        intptr offset);
        void VertexArrayTexCoordOffsetEXT(uint vaobj, uint buffer,
                                          int size, enum type, sizei stride,
                                          intptr offset);
        void VertexArrayMultiTexCoordOffsetEXT(uint vaobj, uint buffer,
                                               enum texunit,
                                               int size, enum type, sizei stride,
                                               intptr offset);
        void VertexArrayFogCoordOffsetEXT(uint vaobj, uint buffer,
                                          enum type, sizei stride,
                                          intptr offset);
        void VertexArraySecondaryColorOffsetEXT(uint vaobj, uint buffer,
                                                int size, enum type,
                                                sizei stride, intptr offset);
        void VertexArrayVertexAttribOffsetEXT(uint vaobj, uint buffer,
                                              uint index, int size,
                                              enum type, boolean normalized,
                                              sizei stride, intptr offset);
        void VertexArrayVertexAttribIOffsetEXT(uint vaobj, uint buffer,
                                               uint index, int size,
                                               enum type, sizei stride,
                                               intptr offset);

    operate identically to the corresponding command where "VertexArray"
    is deleted from the name and "Offset" is changed to "Pointer" (and
    extension suffixes are dropped or updated appropriately) except,
    1) rather than updating the currently in use vertex array object,
    these "VertexArray" commands update the vertex array object named
    by the initial vaobj parameter, and 2) the corresponding command
    operates as if the ARRAY_BUFFER buffer binding is bound to the
    buffer named by the buffer parameter.  The remaining parameters
    following the initial vaobj parameter for the listed "VertexArray"
    commands match the parameters for the corresponding non-"VertexArray"
    vertex array specification command and are interpreted as they
    are for the non-"VertexArray" vertex array specification command.
    The one exception is that final intptr offset parameter of the
    "VertexArray" command is cast to the final pointer parameter of the
    non-"VertexArray" command (intptr is guaranteed to be large enough
    to store any pointer value).

    If the vertex array object named by the vaobj parameter has not
    been previously bound but has been generated (without subsequent
    deletion) by GenVertexArrays, the GL first creates a new state
    vector in the same manner as when BindVertexArray creates a new
    vertex array object.  However these commands fail and an
    INVALID_OPERATION error is generated if vaobj is not a name returned
    from a previous call to GenVertexArrays, or if such a name has since
    been deleted with DeleteVertexArrays.

    If the buffer object named by the buffer parameter is non-zero and
    has not been previously bound or has been deleted since the last
    binding, the GL first creates a new state vector, initialized with
    a zero-sized memory buffer and comprising the state values listed
    in table 2.6.  If the buffer object named by the buffer parameter
    is zero, these commands update the vertex array client-state.

    If the buffer object named by the buffer parameter is non-zero and
    the offset parameter is negative, generate the INVALID_VALUE error.
    No error is generated in the case where buffer is zero because the
    offset might be valid pointer than just happens to be negative when
    cast to a intptr type.

    The following commands:

        void EnableVertexArrayEXT(uint vaobj, enum array);
        void DisableVertexArrayEXT(uint vaobj, enum array);
        void EnableVertexArrayAttribEXT(uint vaobj, uint index);
        void DisableVertexArrayAttribEXT(uint vaobj, uint index);

    operate identically to EnableClientState, DisableClientState,
    EnableVertexAttribArray, and DisableVertexAttribArray respectively
    except rather than updating the current vertex array client-state
    these "VertexArray" commands update the vertex array enables
    within the vertex array object named by the initial vaobj parameter.
    The array parameter matches the array parameter for the corresponding
    EnableClientState and DisableClientState commands.  The index
    parameter matches the index parameter for the corresponding
    EnableVertexAttribArray and DisableVertexAttribArray commands.

    Additionally EnableVertexArrayEXT and DisableVertexArrayEXT accept
    the tokens TEXTURE0 through TEXTUREn where n is less than the
    implementation-dependent limit of MAX_TEXTURE_COORDS.  For these
    GL_TEXTUREi tokens, EnableVertexArrayEXT and DisableVertexArrayEXT
    act identically to EnableVertexArrayEXT(vaobj, TEXTURE_COORD_ARRAY)
    or DisableVertexArrayEXT(vaobj, TEXTURE_COORD_ARRAY) respectively
    as if the active client texture is set to texture coordinate set i
    based on the token TEXTUREi indicated by array.

    If the vertex array object named by the vaobj parameter has not
    been previously bound but has been generated (without subsequent
    deletion) by GenVertexArrays, the GL first creates a new state
    vector in the same manner as when BindVertexArray creates a new
    vertex array object.  However these commands fail and an
    INVALID_OPERATION error is generated if vaobj is not a name returned
    from a previous call to GenVertexArrays, or if such a name has since
    been deleted with DeleteVertexArrays."

    Add to the end of Section 2.12.2 (Matrices):

    "The following commands:

        void MatrixLoadfEXT(enum matrixMode, const float *m);
        void MatrixLoaddEXT(enum matrixMode, const double *m);

        void MatrixLoadTransposefEXT(enum matrixMode, const float *m);
        void MatrixLoadTransposedEXT(enum matrixMode, const double *m);

        void MatrixMultfEXT(enum matrixMode, const float *m);
        void MatrixMultdEXT(enum matrixMode, const double *m);

        void MatrixMultTransposefEXT(enum matrixMode, const float *m);
        void MatrixMultTransposedEXT(enum matrixMode, const double *m);

        void MatrixLoadIdentityEXT(enum matrixMode);

        void MatrixRotatefEXT(enum matrixMode, float angle,
                              float x, float y, float z);
        void MatrixRotatedEXT(enum matrixMode, double angle,
                              double x, double y, double z);

        void MatrixScalefEXT(enum matrixMode,
                             float x, float y, float z);
        void MatrixScaledEXT(enum matrixMode,
                             double x, double y, double z);

        void MatrixTranslatefEXT(enum matrixMode,
                                 float x, float y, float z);
        void MatrixTranslatedEXT(enum matrixMode,
                                 double x, double y, double z);

        void MatrixOrthoEXT(enum matrixMode, double l, double r,
                            double b, double t, double n, double f);
        void MatrixFrustumEXT(enum matrixMode, double l, double r,
                              double b, double t, double n, double f);

        void MatrixPushEXT(enum matrixMode);
        void MatrixPopEXT(enum matrixMode);

    are equivalent (assuming no errors) to the following:

        int savedMatrixMode;

        GetIntegerv(MATRIX_MODE, &savedMatrixMode);
        if (matrixMode >= TEXTURE0 && matrixMode <= TEXTURE31) {
           int savedActiveTexture;

           MatrixMode(TEXTURE);
           GetIntegerv(ACTIVE_TEXTURE, &savedActiveTexture);
           ActiveTexture(matrixMode);
           XXX(...);
           ActiveTexture(savedActiveTexture);
        } else {
           MatrixMode(matrixMode);
           XXX(...);
        }
        MatrixMode(savedMatrixMode);

    where matrixMode is the matrixMode parameter to the listed commands,
    XXX is found in Table 2.selectorFreeMatrixCommands, and ... is the
    list of the remaining arguments for the command that follow the
    initial matrixMode parameter.

    Table 2.selectorFreeMatrixCommands:

        Selector-free Command Name  XXX
        --------------------------  --------------------
        MatrixLoadfEXT              LoadMatrixf
        MatrixLoaddEXT              LoadMatrixd

        MatrixLoadTransposefEXT     LoadTransposeMatrixf
        MatrixLoadTransposedEXT     LoadTransposeMatrixd

        MatrixMultfEXT              MultMatrixf
        MatrixMultdEXT              MultMatrixd

        MatrixMultTransposefEXT     MultTransposeMatrixf
        MatrixMultTransposedEXT     MultTransposeMatrixd

        MatrixLoadIdentityEXT       LoadIdentity

        MatrixRotatefEXT            Rotatef
        MatrixRotatedEXT            Rotated

        MatrixScalefEXT             Scalef
        MatrixScaledEXT             Scaled

        MatrixTranslatefEXT         Translatef
        MatrixTranslatedEXT         Translated

        MatrixOrthoEXT              Ortho
        MatrixFrustumEXT            Frustum

        MatrixPushEXT               PushMatrix
        MatrixPopEXT                PopMatrix"

    Add to the end of Section 2.20.3 (Shader Variables):

    "Program-specific Uniform Updates

    The following commands:

        void ProgramUniform1fEXT(uint program, int location, float v0);
        void ProgramUniform2fEXT(uint program, int location,
                                 float v0, float v1);
        void ProgramUniform3fEXT(uint program, int location,
                                 float v0, float v1, float v2);
        void ProgramUniform4fEXT(uint program, int location,
                                 float v0, float v1, float v2, float v3);

        void ProgramUniform1iEXT(uint program, int location, int v0);
        void ProgramUniform2iEXT(uint program, int location,
                                 int v0, int v1);
        void ProgramUniform3iEXT(uint program, int location,
                                 int v0, int v1, int v2);
        void ProgramUniform4iEXT(uint program, int location,
                                 int v0, int v1, int v2, int v3);

        void ProgramUniform1fvEXT(uint program, int location,
                                  sizei count, const float *value);
        void ProgramUniform2fvEXT(uint program, int location,
                                  sizei count, const float *value);
        void ProgramUniform3fvEXT(uint program, int location,
                                  sizei count, const float *value);
        void ProgramUniform4fvEXT(uint program, int location,
                                  sizei count, const float *value);

        void ProgramUniform1ivEXT(uint program, int location,
                                  sizei count, const int *value);
        void ProgramUniform2ivEXT(uint program, int location,
                                  sizei count, const int *value);
        void ProgramUniform3ivEXT(uint program, int location,
                                  sizei count, const int *value);
        void ProgramUniform4ivEXT(uint program, int location,
                                  sizei count, const int *value);

        void ProgramUniformMatrix2fvEXT(uint program, int location,
                                        sizei count, boolean transpose,
                                        const float *value);
        void ProgramUniformMatrix3fvEXT(uint program, int location,
                                        sizei count, boolean transpose,
                                        const float *value);
        void ProgramUniformMatrix4fvEXT(uint program, int location,
                                        sizei count, boolean transpose,
                                        const float *value);

        void ProgramUniformMatrix2x3fvEXT(uint program, int location,
                                          sizei count, boolean transpose,
                                          const float *value);
        void ProgramUniformMatrix3x2fvEXT(uint program, int location,
                                          sizei count, boolean transpose,
                                          const float *value);
        void ProgramUniformMatrix2x4fvEXT(uint program, int location,
                                          sizei count, boolean transpose,
                                          const float *value);
        void ProgramUniformMatrix4x2fvEXT(uint program, int location,
                                          sizei count, boolean transpose,
                                          const float *value);
        void ProgramUniformMatrix3x4fvEXT(uint program, int location,
                                          sizei count, boolean transpose,
                                          const float *value);
        void ProgramUniformMatrix4x3fvEXT(uint program, int location,
                                          sizei count, boolean transpose,
                                          const float *value);

        void ProgramUniform1uiEXT(uint program, int location, uint v0);
        void ProgramUniform2uiEXT(uint program, int location,
                                  uint v0, uint v1);
        void ProgramUniform3uiEXT(uint program, int location,
                                  uint v0, uint v1, uint v2);
        void ProgramUniform4uiEXT(uint program, int location,
                                  uint v0, uint v1, uint v2, uint v3);

        void ProgramUniform1uivEXT(uint program, int location,
                                   sizei count, const uint *value);
        void ProgramUniform2uivEXT(uint program, int location,
                                   sizei count, const uint *value);
        void ProgramUniform3uivEXT(uint program, int location,
                                   sizei count, const uint *value);
        void ProgramUniform4uivEXT(uint program, int location,
                                   sizei count, const uint *value);

    operate identically to the corresponding command where "Program" is
    deleted from the name (and extension suffixes are dropped or updated
    appropriately) except, rather than updating the currently in use
    program object, these "Program" commands update the program object
    named by the initial program parameter.  The remaining parameters
    following the initial program parameter for the listed "Program"
    commands match the parameters for the corresponding non-"Program"
    uniform command and are interpreted as they are for the non-"Program"
    uniform command.  If the program named by the program parameter
    is not created or has not been successfully linked, the error
    INVALID_OPERATION is generated."

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

    Add to the end of section 3.8.12 (Texture Objects):

    "Texture Object State Update

    The command

        void BindMultiTextureEXT(enum texunit, enum target, uint texture);

    operates identically to BindTexture except, rather than binding the
    named texture object to the current active texture's target binding
    specified by the target parameter, BindMultiTextureEXT binds the
    named texture to the specified target binding of texunit.

    These texture object state update commands:

        void TextureParameteriEXT(uint texture, enum target,
                                  enum pname, int param);
        void TextureParameterivEXT(uint texture, enum target,
                                   enum pname, const int *param);

        void TextureParameterfEXT(uint texture, enum target,
                                  enum pname, float param);
        void TextureParameterfvEXT(uint texture, enum target,
                                   enum pname, const float *param);

        void TextureParameterIivEXT(uint texture, enum target,
                                    enum pname, const int *params);
        void TextureParameterIuivEXT(uint texture, enum target,
                                     enum pname, const uint *params);

        void TextureImage1DEXT(uint texture, enum target,
                               int level, int internalformat,
                               sizei width, int border,
                               enum format, enum type, const void *pixels);
        void TextureImage2DEXT(uint texture, enum target,
                               int level, int internalformat,
                               sizei width, sizei height, int border,
                               enum format, enum type, const void *pixels);

        void TextureSubImage1DEXT(uint texture, enum target,
                                  int level, int xoffset, sizei width,
                                  enum format, enum type,
                                  const void *pixels);
        void TextureSubImage2DEXT(uint texture, enum target,
                                  int level, int xoffset, int yoffset,
                                  sizei width, sizei height,
                                  enum format, enum type,
                                  const void *pixels);

        void CopyTextureImage1DEXT(uint texture, enum target,
                                   int level, enum internalformat,
                                   int x, int y, sizei width, int border);
        void CopyTextureImage2DEXT(uint texture, enum target,
                                   int level, enum internalformat,
                                   int x, int y,
                                   sizei width, sizei height, int border);

        void CopyTextureSubImage1DEXT(uint texture, enum target,
                                      int level, int xoffset,
                                      int x, int y, sizei width);
        void CopyTextureSubImage2DEXT(uint texture, enum target,
                                      int level, int xoffset, int yoffset,
                                      int x, int y,
                                      sizei width, sizei height);

        void TextureImage3DEXT(uint texture, enum target,
                               int level, int internalformat,
                               sizei width, sizei height, sizei depth,
                               int border,
                               enum format, enum type, const void *pixels);

        void TextureSubImage3DEXT(uint texture, enum target,
                                  int level,
                                  int xoffset, int yoffset, int zoffset,
                                  sizei width, sizei height, sizei depth,
                                  enum format, enum type,
                                  const void *pixels);
        void CopyTextureSubImage3DEXT(uint texture, enum target,
                                      int level,
                                      int xoffset, int yoffset, int zoffset,
                                      int x, int y,
                                      sizei width, sizei height);

        void TextureBufferEXT(uint texture, enum target,
                              enum internalformat, uint buffer);

        void CompressedTextureImage3DEXT(uint texture, enum target, int level,
                                         enum internalformat,
                                         sizei width, sizei height,
                                         sizei depth, int border,
                                         sizei imageSize, const void *data);
        void CompressedTextureImage2DEXT(uint texture, enum target, int level,
                                         enum internalformat,
                                         sizei width, sizei height,
                                         int border, sizei imageSize,
                                         const void *data);
        void CompressedTextureImage1DEXT(uint texture, enum target, int level,
                                         enum internalformat,
                                         sizei width, int border,
                                         sizei imageSize, const void *data);
        void CompressedTextureSubImage3DEXT(uint texture, enum target, int level,
                                            int xoffset, int yoffset,
                                            int zoffset,
                                            sizei width, sizei height,
                                            sizei depth, enum format,
                                            sizei imageSize, const void *data);
        void CompressedTextureSubImage2DEXT(uint texture, enum target, int level,
                                            int xoffset, int yoffset,
                                            sizei width, sizei height,
                                            enum format,
                                            sizei imageSize, const void *data);
        void CompressedTextureSubImage1DEXT(uint texture, enum target, int level,
                                            int xoffset, sizei width,
                                            enum format,
                                            sizei imageSize, const void *data);
        void CompressedTextureImage3DEXT(uint texture, enum target, int level,
                                         enum internalformat,
                                         sizei width, sizei height,
                                         sizei depth, int border,
                                         sizei imageSize, const void *data);

        void TextureBufferEXT(uint texture, enum target,
                              enum internalformat, uint buffer);

        void TextureRenderbufferEXT(uint texture, enum target,
                                    uint renderbuffer);

    operate identically to the corresponding command where "Texture"
    is substituted for "Tex" (and extension suffixes are dropped or
    updated appropriately) except, rather than updating the current bound
    texture for the texture unit indicated by the current active texture
    state and the target parameter, these "Texture" commands update the
    texture object named by the initial texture parameter.  If the
    texture parameter is zero, then the target parameter selects the
    default texture of the specified target to update.  The remaining
    parameters following the initial texture parameter for the listed
    "Texture" commands match the parameters for the corresponding "Tex"
    command and are interpreted as they are for the "Tex" command.
    If the texture parameter is for an unused name, the name becomes
    used and the named texture object is set to a new state vector,
    comprising all the state values listed in section 3.8.11, set
    to the same initial values prior to the command's state update.
    If the texture parameter is for a used name and that named texture
    object has a different target than the specified target parameter,
    the INVALID_OPERATION error is generated.  One consequence of this
    error for commands that accepts TEXTURE_PROXY_* as a valid target
    parameter is TEXTURE_PROXY_* target tokens generate errors if used
    with a non-zero texture parameter because the target of a non-default
    (non-zero) texture object is never a proxy target."

    Add before the last paragraph of Section 3.8.16 (Texture Application):

    "The following commands (introduced by EXT_draw_buffers2):

        void EnableIndexedEXT(enum cap, uint index);
        void Enablei(enum cap, uint index);
        void DisableIndexedEXT(enum cap, uint index);
        void Disablei(enum cap, uint index);

    are equivalent (assuming no errors) to the following:

        int savedActiveTexture;

        GetIntegerv(ACTIVE_TEXTURE, &savedActiveTexture);
        ActiveTexture(TEXTURE0+index);
        XXX(cap);
        ActiveTexture(savedActiveTexture);

    where index is the index parameter to the listed commands and XXX
    is the name of the command without its "Indexed" or "i" suffix
    (either Enable or Disable) when the cap parameter is one of
    the texture-related enable token depending on the active texture
    state, namely TEXTURE_1D, TEXTURE_2D, TEXTURE_3D, TEXTURE_CUBE_MAP,
    TEXTURE_RECTANGLE_ARB, TEXTURE_GEN_S, TEXTURE_GEN_T, TEXTURE_GEN_R,
    or TEXTURE_GEN_Q."

    Add NEW section 3.8.X (Multitexture Commands): after section 3.8.16
    (Texture Application):

    "These multitexture commands:

        void MultiTexCoordPointerEXT(enum texunit, int size, enum type,
                                     sizei stride, const void *pointer);

        void MultiTexEnvfEXT(enum texunit, enum target, enum pname,
                             float param);
        void MultiTexEnvfvEXT(enum texunit, enum target, enum pname,
                              const float *params);
        void MultiTexEnviEXT(enum texunit, enum target, enum pname,
                             int param);
        void MultiTexEnvivEXT(enum texunit, enum target, enum pname,
                              const int *params);

        void MultiTexGendEXT(enum texunit, enum coord, enum pname,
                             double param);
        void MultiTexGendvEXT(enum texunit, enum coord, enum pname,
                              const double *params);
        void MultiTexGenfEXT(enum texunit, enum coord, enum pname,
                             float param);
        void MultiTexGenfvEXT(enum texunit, enum coord, enum pname,
                              const float *params);
        void MultiTexGeniEXT(enum texunit, enum coord, enum pname,
                             int param);
        void MultiTexGenivEXT(enum texunit, enum coord, enum pname,
                              const int *params);

        void MultiTexParameteriEXT(enum texunit, enum target,
                                   enum pname, int param);
        void MultiTexParameterivEXT(enum texunit, enum target,
                                    enum pname, const int *param);

        void MultiTexParameterfEXT(enum texunit, enum target,
                                   enum pname, float param);
        void MultiTexParameterfvEXT(enum texunit, enum target,
                                    enum pname, const float *param);

        void MultiTexParameterIivEXT(enum texunit, enum target,
                                     enum pname, const int *params);
        void MultiTexParameterIuivEXT(enum texunit, enum target,
                                      enum pname, const uint *params);

        void MultiTexImage1DEXT(enum texunit, enum target,
                                int level, int internalformat,
                                sizei width, int border,
                                enum format, enum type, const void *pixels);
        void MultiTexImage2DEXT(enum texunit, enum target,
                                int level, int internalformat,
                                sizei width, sizei height, int border,
                                enum format, enum type, const void *pixels);

        void MultiTexSubImage1DEXT(enum texunit, enum target,
                                   int level, int xoffset, sizei width,
                                   enum format, enum type,
                                   const void *pixels);
        void MultiTexSubImage2DEXT(enum texunit, enum target,
                                   int level, int xoffset, int yoffset,
                                   sizei width, sizei height,
                                   enum format, enum type,
                                   const void *pixels);

        void CopyMultiTexImage1DEXT(enum texunit, enum target,
                                    int level, enum internalformat,
                                    int x, int y, sizei width, int border);
        void CopyMultiTexImage2DEXT(enum texunit, enum target,
                                    int level, enum internalformat,
                                    int x, int y,
                                    sizei width, sizei height, int border);

        void CopyMultiTexSubImage1DEXT(enum texunit, enum target,
                                       int level, int xoffset,
                                       int x, int y, sizei width);
        void CopyMultiTexSubImage2DEXT(enum texunit, enum target,
                                       int level, int xoffset, int yoffset,
                                       int x, int y,
                                       sizei width, sizei height);

        void MultiTexImage3DEXT(enum texunit, enum target,
                                int level, int internalformat,
                                sizei width, sizei height, sizei depth,
                                int border,
                                enum format, enum type, const void *pixels);

        void MultiTexSubImage3DEXT(enum texunit, enum target,
                                   int level,
                                   int xoffset, int yoffset, int zoffset,
                                   sizei width, sizei height, sizei depth,
                                   enum format, enum type,
                                   const void *pixels);
        void CopyMultiTexSubImage3DEXT(enum texunit, enum target,
                                       int level,
                                       int xoffset, int yoffset, int zoffset,
                                       int x, int y,
                                       sizei width, sizei height);

        void CompressedMultiTexImage3DEXT(enum texunit, enum target, int level,
                                          enum internalformat,
                                          sizei width, sizei height,
                                          sizei depth, int border,
                                          sizei imageSize, const void *data);
        void CompressedMultiTexImage2DEXT(enum texunit, enum target, int level,
                                          enum internalformat,
                                          sizei width, sizei height,
                                          int border, sizei imageSize,
                                          const void *data);
        void CompressedMultiTexImage1DEXT(enum texunit, enum target, int level,
                                          enum internalformat,
                                          sizei width, int border,
                                          sizei imageSize, const void *data);
        void CompressedMultiTexSubImage3DEXT(enum texunit, enum target, int level,
                                             int xoffset, int yoffset,
                                             int zoffset,
                                             sizei width, sizei height,
                                             sizei depth, enum format,
                                             sizei imageSize, const void *data);
        void CompressedMultiTexSubImage2DEXT(enum texunit, enum target, int level,
                                             int xoffset, int yoffset,
                                             sizei width, sizei height,
                                             enum format,
                                             sizei imageSize, const void *data);
        void CompressedMultiTexSubImage1DEXT(enum texunit, enum target, int level,
                                             int xoffset, sizei width,
                                             enum format,
                                             sizei imageSize, const void *data);

        void MultiTexBufferEXT(enum texunit, enum target,
                               enum internalformat, uint buffer);

        void MultiTexRenderbufferEXT(enum texunit, enum target,
                                     uint renderbuffer);

    are equivalent (assuming no errors) to the following:

        int savedActiveTexture;

        GetIntegerv(ACTIVE_TEXTURE, &savedActiveTexture);
        ActiveTexture(texunit);
        XXX(...);
        ActiveTexture(savedActiveTexture);

    where XXX is the name of the command without its "Multi" prefix
    (and extension suffixes are dropped or updated appropriately)
    and ... is the list of the arguments for the command excluding the
    index parameter."

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

    Add new section 4.4.7 (Named Access):

    "The following commands:

        void NamedRenderbufferStorageEXT(uint renderbuffer,
                                         enum internalformat,
                                         sizei width, sizei height);

        void NamedRenderbufferStorageMultisampleEXT(uint renderbuffer,
                                                    sizei samples,
                                                    enum internalformat,
                                                    sizei width, sizei height);

        void NamedRenderbufferStorageMultisampleCoverageEXT(uint renderbuffer,
                                                            sizei coverageSamples, 
                                                            sizei colorSamples,
                                                            enum internalformat,
                                                            sizei width,
                                                            sizei height);

    operate identically to the corresponding command where "Named" is
    deleted from the name (and extension suffixes are dropped or updated
    appropriately) except, rather than updating the currently bound
    renderbuffer for the renderbuffer target parameter (a parameter not
    present for these listed commands), these "Named" commands update the
    renderbuffer object named by the initial renderbuffer parameter.
    The remaining parameters following the initial renderbuffer
    parameter for the listed "Named" commands match the parameters
    for the corresponding non-"Named" renderbuffer command and are
    interpreted as they are for the non-"Named" renderbuffer command;
    and the target parameter is assumed to be RENDERBUFFER.  If the
    renderbuffer object named by the renderbuffer parameter has not
    been previously bound or has been deleted since the last binding,
    the GL first creates a new state vector in the same manner as when
    BindRenderbuffer creates a new renderbuffer object.

    The following commands (and query):

        void NamedFramebufferTexture1DEXT(uint framebuffer,
                                          enum attachment,
                                          enum textarget, uint texture,
                                          int level);
        void NamedFramebufferTexture2DEXT(uint framebuffer,
                                          enum attachment,
                                          enum textarget, uint texture,
                                          int level);
        void NamedFramebufferTexture3DEXT(uint framebuffer,
                                          enum attachment,
                                          enum textarget, uint texture,
                                          int level, int zoffset);

        void NamedFramebufferRenderbufferEXT(uint framebuffer,
                                             enum attachment,
                                             enum renderbuffertarget,
                                             uint renderbuffer);

        void NamedFramebufferTextureEXT(uint framebuffer, enum attachment, 
                                        uint texture, int level);
        void NamedFramebufferTextureLayerEXT(uint framebuffer,
                                             enum attachment, 
                                             uint texture,
                                             int level, int layer);
        void NamedFramebufferTextureFaceEXT(uint framebuffer, enum attachment,
                                            uint texture,
                                            int level, enum face);

        void GetNamedFramebufferAttachmentParameterivEXT(uint framebuffer,
                                                         enum attachment,
                                                         enum pname,
                                                         int *params);

    operate identically to the corresponding command (or query) where
    "Named" is deleted from the name (and extension suffixes are dropped
    or updated appropriately) except, rather than updating the currently
    bound framebuffer for the framebuffer target parameter (a parameter
    not present for these listed commands and query), these "Named"
    commands update (or the query queries) the framebuffer object named by
    the initial framebuffer parameter.  The remaining parameters following
    the initial framebuffer parameter for the listed "Named" commands
    (or query) match the parameters for the corresponding non-"Named"
    framebuffer command (or query) and are interpreted as they are for the
    non-"Named" framebuffer command (or query); and the target parameter is
    assumed to be FRAMEBUFFER.  If the framebuffer object named by
    the framebuffer parameter has not been previously bound or has been
    deleted since the last binding, the GL first creates a new state
    vector in the same manner as when BindFramebuffer creates a new
    framebuffer object.

    The commands

        void FramebufferDrawBufferEXT(uint framebuffer, enum mode);
        void FramebufferDrawBuffersEXT(uint framebuffer, sizei n,
                                       const enum *bufs)
        void FramebufferReadBufferEXT(uint framebuffer, enum mode);


    operate identically to DrawBuffer, DrawBuffers, and ReadBuffer
    (without the initial framebuffer parameter) respectively except rather
    than updating the draw buffers or read buffer of the currently bound
    framebuffer object or the default window-system-provided framebuffer
    (i.e., FRAMEBUFFER_BINDING is zero), these commands update the
    draw buffers or read buffer of the framebuffer object named by the
    framebuffer parameter.  When the framebuffer parameter is zero,
    the default window-system provided framebuffer is updated (even if
    the window-system-provided framebuffer is not currently bound).
    If the framebuffer object named by the framebuffer parameter has not
    been previously bound or has been deleted since the last binding,
    the GL first creates a new state vector in the same manner as when
    BindFramebuffer creates a new framebuffer object.

    The query

        void GetFramebufferParameterivEXT(uint framebuffer, enum pname,
                                          int *param);

    returns the framebuffer state of the framebuffer object specified
    by the framebuffer parameter.  The pname parameter must be one of
    framebuffer dependent values listed in either table 4.nnn (namely
    DRAW_BUFFER, READ_BUFFER, or DRAW_BUFFER0 through DRAW_BUFFER15).
    The query returns the same value in param that GetIntegerv would
    return if called with pname and param as if the framebuffer specified
    by the framebuffer parameter had been bound with BindFramebuffer.
    If the framebuffer object named by the framebuffer parameter has not
    been previously bound or has been deleted since the last binding,
    the GL first creates a new state vector in the same manner as when
    BindFramebuffer creates a new framebuffer object.

    The command

        enum CheckNamedFramebufferStatusEXT(uint framebuffer,
                                            enum target);

    operates identically to CheckFramebufferStatus except rather
    than checking the currently bound framebuffer for the framebuffer
    target parameter, the status of the named framebuffer is checked
    where the target parameter indicates how the framebuffer would
    be bound.  Because FRAMEBUFFER_UNSUPPORTED can be returned by
    CheckFramebufferStatus due to an implementation-dependent set of
    restrictions that might not be known until the framebuffer object is
    bound with BindFramebuffer, CheckNamedFramebufferStatusARB may in
    rare circumstances (ideally never) return FRAMEBUFFER_COMPLETE
    when CheckFramebufferStatus with the same framebuffer object bound
    would return FRAMEBUFFER_UNSUPPORTED.  The framebuffer is checked
    for drawing if target is FRAMEBUFFER or DRAW_FRAMEBUFFER,
    and checked for reading if the target is READ_FRAMEBUFFER.
    If the framebuffer object named by the framebuffer parameter has not
    been previously bound or has been deleted since the last binding,
    the GL first creates a new state vector in the same manner as when
    BindFramebuffer creates a new framebuffer object.

    The commands

        void GenerateTextureMipmapEXT(uint texture, enum target);

        void GenerateMultiTexMipmapEXT(enum texunit, enum target);

    operate identically to GenerateMipmap except they use the
    texture specified by the named texture or specified texture unit
    respectively.  The target parameter must be a token accepted by
    GenerateMipmap.

    If GenerateTextureMipmapARB's texture parameter is for an unused
    name, the name becomes used and the named texture object is set
    to a new state vector, comprising all the state values listed in
    section 3.8.11, set to the same initial values prior to the command's
    state update.  If the texture parameter is for a used name and that
    named texture object has a different target than the specified target
    parameter, the INVALID_OPERATION error is generated."

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

    In Section 5.4 (Display Lists):

    Add to list (page 310) of "Client state" commands "not compiled into
    the display list but are executed immediately":

        PushClientAttribDefaultEXT, ClientAttribDefaultEXT

    Add to list (page 310) of "Framebuffer and renderbuffer objects"
    commands "not compiled into the display list but are executed
    immediately":

         CheckNamedFramebufferStatusEXT, NamedRenderbufferStorageEXT,
         NamedFramebufferTexture1DEXT, NamedFramebufferTexture2DEXT,
         NamedFramebufferTexture3DEXT, NamedFramebufferRenderbufferEXT,
         GenerateTextureMipmapEXT, GenerateMultiTexMipmapEXT

    Add to the list (page 310) of "Vertex Buffer Objects" commands
    "not compiled into the display list but are executed immediately":
    
         NamedCopyBufferSubDataEXT

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

    Change section 6.1.1 (Simple Queries) so the second and third
    paragraphs read:

    "Indexed simple state variables are queried with the commands:

        void GetBooleani_v(enum target, uint index, boolean *data);
        void GetIntegeri_v(enum target, uint index, int *data);
        void GetFloati_vEXT(enum target, uint index, float *data);
        void GetDoublei_vEXT(enum target, uint index, double *data);

        void GetBooleanIndexedvEXT(enum target, uint index, boolean *data);
        void GetIntegerIndexedvEXT(enum target, uint index, int *data);
        void GetFloatIndexedvEXT(enum target, uint index, float *data);
        void GetDoubleIndexedvEXT(enum target, uint index, double *data);

    target is the name of the indexed state and index is the index of
    the particular element being queried.  data is a pointer to a scalar
    or array of the indicated type in which to place the returned data.
    An INVALID_VALUE error is generated if index is outside the valide
    range for the indexed state target.

    Table 6.indexedGenericQueryCommands:

        Selector-free Command Name  GetXXX
        --------------------------  --------------------
        GetBooleanIndexedvEXT       GetBooleanv
        GetIntegerIndexedvEXT       GetIntegerv
        GetFloatIndexedvEXT         GetFloatv
        GetDoubleIndexedvEXT        GetDoublev
        GetBooleani_v               GetBooleanv
        GetIntegeri_v               GetIntegerv
        GetFloati_vEXT              GetFloatv
        GetDoublei_vEXT             GetDoublev

    When the target to one of these indexed queries is one
    of PROGRAM_MATRIX_EXT, TRANSPOSE_PROGRAM_MATRIX_EXT, or
    PROGRAM_MATRIX_STACK_DEPTH_EXT, the query operates indentically to
    (assuming no errors):

        int savedMatrixMode;
        GetIntegerv(MATRIX_MODE, &savedMatrixMode);
        MatrixMode(GL_MATRIX0_ARB+index);
        switch (target) {
        case PROGRAM_MATRIX_EXT:
            GetXXX(CURRENT_MATRIX_ARB, params);
            break;
        case TRANSPOSE_PROGRAM_MATRIX_EXT:
            GetXXX(TRANSPOSE_CURRENT_MATRIX_ARB, params);
            break;
        case PROGRAM_MATRIX_STACK_DEPTH_EXT:
            GetXXX(CURRENT_MATRIX_STACK_DEPTH_ARB, params);
            break;
        }
        MatrixMode(savedMatrixMode);

    where GetXXX is found in Table 6.indexedGenericQueryCommands.

    When the target to one of these indexed queries is one
    of CURRENT_MATRIX_NV, CURRENT_MATRIX_STACK_DEPTH_NV,
    CURRENT_RASTER_TEXTURE_COORDS, CURRENT_TEXTURE_COORDS,
    TEXTURE_BINDING_1D, TEXTURE_BINDING_1D_ARRAY,
    TEXTURE_BINDING_2D, TEXTURE_BINDING_2D_ARRAY,
    TEXTURE_BINDING_3D, TEXTURE_BINDING_BUFFER_EXT,
    TEXTURE_BINDING_CUBE_MAP, TEXTURE_BINDING_CUBE_MAP_ARRAY_NV,
    TEXTURE_BINDING_RECTANGLE_ARB, TEXTURE_BINDING_RENDERBUFFER_NV,
    TEXTURE_RENDERBUFFER_DATA_STORE_BINDING_NV,
    TEXTURE_BUFFER_DATA_STORE_BINDING_EXT, TEXTURE_BUFFER_FORMAT_EXT,
    TEXTURE_GEN_Q, TEXTURE_GEN_R, TEXTURE_GEN_S, TEXTURE_GEN_T,
    TEXTURE_MATRIX, TEXTURE_STACK_DEPTH, TRANSPOSE_TEXTURE_MATRIX,
    GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP, or
    GL_TEXTURE_RECTANGLE_ARB, the query operates indentically (assuming
    no errors) to:

        int savedActiveTexture;
        GetIntegerv(ACTIVE_TEXTURE, &savedActiveTexture);
        ActiveTexture(TEXTURE0+index);
        GetXXX(target, params);
        ActiveTexture(savedActiveTexture);

    where GetXXX is found in Table 6.indexedGenericQueryCommands.

    When the target to one of these indexed queries is one of
    TEXTURE_COORD_ARRAY, TEXTURE_COORD_ARRAY_BUFFER_BINDING,
    TEXTURE_COORD_ARRAY_COUNT, TEXTURE_COORD_ARRAY_SIZE,
    TEXTURE_COORD_ARRAY_STRIDE, or TEXTURE_COORD_ARRAY_TYPE, the query
    operates indentically (assuming no errors) to:

        int savedClientActiveTexture;
        GetIntegerv(CLIENT_ACTIVE_TEXTURE, &savedClientActiveTexture);
        ClientActiveTexture(TEXTURE0+index);
        GetXXX(target, params);
        ClientActiveTexture(savedClientActiveTexture);

    where GetXXX is found in Table 6.indexedGenericQueryCommands.

    Finally,

        boolean IsEnabled(enum value);

    can be used to determine if value is currently enabled (as with
    Enable) or disabled and the queries

        boolean IsEnabledi(enum target, uint index);
        boolean IsEnabledIndexedEXT(enum cap, uint index);

    can be used to determine if the indexed state corresponding to target
    and index is enabled or disabled.  An INVALID_VALUE error is generated
    if index is outside the valid range for the indexed state target.

    When the target to IsEnabledi or IsEnabledIndexedEXT is
    one of TEXTURE_1D, TEXTURE_2D, TEXTURE_3D, TEXTURE_CUBE_MAP,
    TEXTURE_RECTANGLE_ARB, TEXTURE_GEN_S, TEXTURE_GEN_T, TEXTURE_GEN_R,
    or TEXTURE_GEN_Q, the query operates indentically (assuming no
    errors) to:

        int savedActiveTexture;
        boolean rv;
        GetIntegerv(ACTIVE_TEXTURE, &savedActiveTexture);
        ActiveTexture(TEXTURE0+index);
        rv = IsEnabled(cap);
        ActiveTexture(savedActiveTexture);
        return rv;

    When the target to IsEnabledi or IsEnabledIndexedEXT is
    TEXTURE_COORD_ARRAY, the query operates indentically (assuming no
    errors) to:

        int savedClientActiveTexture;
        boolean rv;
        GetIntegerv(CLIENT_ACTIVE_TEXTURE, &savedClientActiveTexture);
        ClientActiveTexture(TEXTURE0+index);
        rv = IsEnabled(cap);
        ClientActiveTexture(savedClientActiveTexture);
        return rv;"

    Add new paragraph to the end of section 6.1.3 (Enumerated Queries):

    "These commands

        void GetTextureImageEXT(uint texture, enum target,
                                int level,
                                enum format, enum type, void *pixels);

        void GetTextureParameterfvEXT(uint texture, enum target,
                                      enum pname, float *params);
        void GetTextureParameterivEXT(uint texture, enum target,
                                      enum pname, int *params);

        void GetTextureLevelParameterfvEXT(uint texture, enum target,
                                           int level,
                                           enum pname, float *params);
        void GetTextureLevelParameterivEXT(uint texture, enum target,
                                           int level,
                                           enum pname, int *params);

        void GetTextureParameterIivEXT(uint texture, enum target,
                                       enum pname, int *params);
        void GetTextureParameterIuivEXT(uint texture, enum target,
                                        enum pname, uint *params);

    operate identically to the corresponding texture query command where
    "Texture" is substituted for "Tex" (and extension suffixes are dropped
    or updated appropriately) except, rather than querying the current
    bound texture for the texture unit indicated by the current active
    texture state and the target parameter, these "Texture" commands
    query the texture object named by the initial texture parameter.
    The remaining parameters following the initial texture parameter
    for the listed "Texture" commands match the parameters for the
    corresponding "Tex" command and are interpreted as they are for the
    "Tex" command." If the texture parameter is for an unused name, the
    name becomes used and the named texture object is set to a new state
    vector, comprising all the state values listed in section 3.8.11,
    set to the same initial values prior to the command's state query.
    If the texture parameter is for a used name and that named texture
    object has a different target than the specified target parameter,
    the INVALID_OPERATION error is generated.  One consequence of this
    error for commands that accepts TEXTURE_PROXY_* as a valid target
    parameter (GetTextureLevelParameter*, but not GetTextureParameter*)
    is TEXTURE_PROXY_* target tokens generate errors if used with a
    non-zero texture parameter because the target of a non-default
    (non-zero) texture object is never a proxy target."

    Add new paragraph after the GetPointerv description in section 6.1.11
    (Pointer and String Queries):

    "The following query

        void GetPointerIndexedvEXT(enum pname, uint index, void **params);

    is equivalent (assuming no errors) to the following:

        int savedClientActiveTexture;

        GetIntegerv(CLIENT_ACTIVE_TEXTURE, &savedClientActiveTexture);
        ClientActiveTexture(TEXTURE0+index);
        GetPointerv(pname, params);
        ClientActiveTexture(savedClientActiveTexture);

    where index is the index parameter to the listed queries and GetXXX
    is found in Table 6.indexedGenericQueryCommands.  when the pname
    parameter is TEXTURE_COORD_ARRAY_POINTER."

    Add new paragraph to the end of section 6.1.13 (Buffer Object Queries):

    "These commands

        void GetNamedBufferParameterivEXT(uint buffer,
                                          enum pname, int *params);
        void GetNamedBufferPointervEXT(uint buffer,
                                       enum pname, void* *params);
        void GetNamedBufferSubDataEXT(uint buffer,
                                      intptr offset, sizeiptr size, void *data);

    operate identically to the corresponding command where "Named" is
    deleted from the name (and extension suffixes are dropped or updated
    appropriately) except, rather than querying the currently bound buffer
    for the buffer target parameter (a parameter not present for these
    listed commands), these "Named" commands query the buffer object
    named by the initial buffer parameter.  The remaining parameters
    following the initial buffer parameter for the listed "Named" commands
    match the parameters for the corresponding non-"Named" buffer command
    (except the target parameter is not needed because the buffer object
    to query is identified by its name) and are interpreted as they
    are for the non-"Named" buffer command.  If the buffer object named
    by the buffer parameter has not been previously bound or has been
    deleted since the last binding, the GL first creates a new state
    vector, initialized with a zero-sized memory buffer and comprising the
    state values listed in table 2.6.  There is no buffer corresponding
    to the name zero, these commands generate the INVALID_OPERATION
    error if the buffer parameter is zero."

    Add new paragraph to the end of section after 6.1.14 (Vertex Array
    Object Queries):

    "The commands

        void GetVertexArrayIntegervEXT(uint vaobj, enum pname,
                                       int *param);
        void GetVertexArrayPointervEXT(uint vaobj, enum pname,
                                       void **param);
        void GetVertexArrayIntegeri_vEXT(uint vaobj,
                                         uint index,
                                         enum pname,
                                         int *param);
        void GetVertexArrayPointeri_vEXT(uint vaobj,
                                         uint index,
                                         enum pname,
                                         void **param);

    queries the parameters of the vertex array object named by vaobj.  For
    GetVertexArrayIntegervEXT, pname must be one of the "Get value" tokens
    in tables 6.6, 6.7, 6.8, and 6.9 that use GetIntegerv, IsEnabled, or
    GetPointerv for their "Get command" (so excluding the VERTEX_ATTRIB_*
    tokens).  For GetVertexArrayIntegeri_vEXT, pname must be one of the
    "Get value" tokens in tables 6.8 and 6.9 that use GetVertexAttribiv
    or GetVertexAttribPointerv (so allowing only the VERTEX_ATTRIB_*
    tokens) or a token of the form TEXTURE_COORD_ARRAY (the enable) or
    TEXTURE_COORD_ARRAY_*; index identifies the vertex attribute
    array to query or texture coordinate set index respectively.  For
    GetVertexArrayPointervEXT, pname must be a *_ARRAY_POINTER token from
    tables 6.6, 6.7, and 6.8 excluding VERTEX_ATTRIB_ARRAY_POINTER.  For
    GetVertexArrayPointeri_vEXT, pname must be VERTEX_ATTRIB_ARRAY_POINTER
    or TEXTURE_COORD_ARRAY_POINTER with the index parameter indicating
    the vertex attribute or texture coordindate set index.

    If the state queried by GetVertexArrayIntegervEXT or
    GetVertexArrayVertexAttribIntegervEXT is maintained as a pointer,
    the least significant bits of the pointer that fit within an int are
    returned in case a pointer is larger than an int.  This behavior
    allows pointers treated as offsets (when less than 2^31) to be
    returned as integer values.

    If the vertex array object named by the vaobj parameter has not
    been previously bound but has been generated (without subsequent
    deletion) by GenVertexArrays, the GL first creates a new state
    vector in the same manner as when BindVertexArray creates a new
    vertex array object (hence the initial state will be returned).
    However these queries fail and an INVALID_OPERATION error is
    generated if vaobj is not a name returned from a previous call
    to GenVertexArrays, or if such a name has since been deleted with
    DeleteVertexArrays."

    Add NEW section after 6.1.15 (Shader and Program Queries):

    "16.1.X  Multitexture Queries

    These queries

        void GetMultiTexEnvfvEXT(enum texunit, enum target,
                                 enum pname, float *params);
        void GetMultiTexEnvivEXT(enum texunit, enum target,
                                 enum pname, int *params);

        void GetMultiTexGendvEXT(enum texunit, enum coord,
                                 enum pname, double *params);
        void GetMultiTexGenfvEXT(enum texunit, enum coord,
                                 enum pname, float *params);
        void GetMultiTexGenivEXT(enum texunit, enum coord,
                                 enum pname, int *params);

        void GetMultiTexImageEXT(enum texunit, enum target,
                                 int level,
                                 enum format, enum type, void *pixels);

        void GetMultiTexParameterfvEXT(enum texunit, enum target,
                                       enum pname, float *params);
        void GetMultiTexParameterivEXT(enum texunit, enum target,
                                       enum pname, int *params);

        void GetMultiTexParameterIivEXT(enum texunit, enum target,
                                        enum pname, int *params);
        void GetMultiTexParameterIuivEXT(enum texunit, enum target,
                                         enum pname, uint *params);

        void GetMultiTexLevelParameterfvEXT(enum texunit, enum target,
                                            int level,
                                            enum pname, float *params);
        void GetMultiTexLevelParameterivEXT(enum texunit, enum target,
                                            int level,
                                            enum pname, int *params);

        void GetCompressedMultiTexImageEXT(enum texunit, enum target,
                                           int level, void *img);

    are equivalent (assuming no errors) to the following:

        int savedActiveTexture, savedClientActiveTexture;

        GetIntegerv(ACTIVE_TEXTURE, &savedActiveTexture);
        ActiveTexture(texunit);
        GetXXX(...);
        ActiveTexture(savedActiveTexture);

    where GetXXX is found in Table 6.MultiTexQueryCommands and
    ... is the list of the arguments for the command excluding the
    index parameter.

    Table 6.MultiTexQueryCommands:

        Selector-free Command Name       GetXXX
        ------------------------------   --------------------
        GetMultiTexEnvfvEXT              GetTexEnvfv
        GetMultiTexEnvivEXT              GetTexEnviv
        GetMultiTexGendvEXT              GetTexGendv
        GetMultiTexGenfvEXT              GetTexGenfv
        GetMultiTexGenivEXT              GetTexGeniv
        GetMultiTexImageEXT              GetTexImage
        GetMultiTexParameterfvEXT        GetTexParameterfv
        GetMultiTexParameterivEXT        GetTexParameteriv
        GetMultiTexParameterIivEXT       GetTexParameterIiv
        GetMultiTexParameterIuivEXT      GetTexParameterIuiv
        GetMultiTexLevelParameterivEXT   GetTexLevelParameteriv
        GetMultiTexLevelParameterfvEXT   GetTexLevelParameterfv
        GetCompressedMultiTexImageEXT    GetCompressedTexImage

    Add new paragraphs after the first paragraph of section 6.1.15
    (Saving and Restoring State):

    "The command

        void ClientAttribDefaultEXT(bitfield mask);

     resets portions of the client state, depending on the bits set
     in the mask parameter, to the initial values of the state.
     When CLIENT_PIXEL_STORE_BIT is set in mask, the pixel store
     state is set to the initial values documented in table 6.23.
     When CLIENT_VERTEX_ARRAY_BIT is set in mask, the client vertex
     array state is set to the initial values documented in table 6.6,
     6.7, and 6.8.

     The command

        void PushClientAttribDefaultEXT(bitfield mask);

     is equivalent to:

        PushClientAttrib(mask);
        ClientAttribDefaultEXT(mask);"

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

    None.

Interactions with the ARB_texture_rectangle specification

    If ARB_texture_rectangle (or NV_texture_rectangle or
    EXT_texture_rectangle) is NOT supported, ignore references to
    TEXTURE_RECTANGLE_ARB and GL_TEXTURE_BINDING_RECTANGLE_ARB in amended
    section 3.8.16 and new section 6.1.X.

Interactions with the ARB_vertex_program specification

    If ARB_vertex_program is NOT supported, ignore the support
    for PROGRAM_MATRIX_EXT, TRANSPOSE_PROGRAM_MATRIX_EXT,
    and PROGRAM_MATRIX_STACK_DEPTH_EXT described for the
    GetBooleanIndexedvEXT, GetIntegerIndexedvEXT, GetFloatIndexedvEXT,
    and GetDoubleIndexedvEXT commands in section 6.1.X.

Additions to the ARB_vertex_program specification

    Add to the end of section 2.14.1 (Program Objects):

    "This command

        void NamedProgramStringEXT(uint program, enum target, enum format,
                                   sizei len, const void *string); 

    operates identically to ProgramStringARB except, rather than
    specifying the string for the currently bound program for the program
    target parameter, NamedProgramStringARB specifies the program string
    for the program object named by the initial program parameter.

    If the program parameter is for an unused program, the name becomes
    used and the named program object is set to a new program state
    vector as if BindProgramARB had been called on the unused program
    name with the given target parameter but without changing the target's
    program binding.

    If the program parameter is for a used name and that named program
    object has a different target than the specified target parameter,
    the INVALID_OPERATION error is generated.

    These commands

        void NamedProgramLocalParameter4dEXT(uint program, enum target,
                                             uint index,
                                             double x, double y,
                                             double z, double w);
        void NamedProgramLocalParameter4dvEXT(uint program, enum target,
                                              uint index,
                                              const double *params);
        void NamedProgramLocalParameter4fEXT(uint program, enum target,
                                             uint index,
                                             float x, float y,
                                             float z, float w);
        void NamedProgramLocalParameter4fvEXT(uint program, enum target,
                                              uint index,
                                              const float *params);

    operate identically to the corresponding command where "Named"
    is deleted from the name (and extension suffixes are updated to
    ARB appropriately) except, rather than updating the currently bound
    program for the program target parameter (a parameter not present for
    these listed commands), these "Named" commands update the program
    object named by the initial program parameter.  If the program
    parameter is zero, then the target parameter selects the default
    program of the specified target to update.  The remaining parameters
    following the initial program parameter for the listed "Named"
    commands match the parameters for the corresponding non-"Named"
    command and are interpreted as they are for the non-"Named" command.
    If the program parameter is for an unused name, the name becomes
    used and the named program object is assigned target-specific
    default values (see section 2.14.7 for vertex programs or section
    3.11.8 for fragment programs), set to the same initial values prior to
    the command's state update.  If the program parameter is for a used
    name and that named program object has a different target than the
    specified target parameter, the INVALID_OPERATION error is generated."

    Add to the end of section 6.1.12 (Program Queries):

    "These queries

        void GetNamedProgramLocalParameterdvEXT(uint program, enum target,
                                                uint index,
                                                double *params);
        void GetNamedProgramLocalParameterfvEXT(uint program, enum target,
                                                uint index,
                                                float *params);
        void GetNamedProgramivEXT(uint program, enum target,
                                  enum pname, int *params);
        void GetNamedProgramStringEXT(uint program, enum target,
                                      enum pname, void *string);

    operate identically to the corresponding query where "Named" is
    deleted from the name (and extension suffixes are updated to ARB
    appropriately) except, rather than querying the currently bound
    program for the program target parameter (a parameter not present for
    these listed query), these "Named" queries query the program object
    named by the initial program parameter.  If the program parameter
    is zero, then the target parameter selects the default program of
    the specified target to query.  The remaining parameters following
    the initial program parameter for the listed "Named" queries match
    the parameters for the corresponding non-"Named" query and are
    interpreted as they are for the non-"Named" query.  If the program
    parameter is for an unused name, the name becomes used and the named
    program object is assigned target-specific default values (see section
    2.14.7 for vertex programs or section 3.11.8 for fragment programs),
    set to the same initial values prior to the query's state query.
    If the program parameter is for a used name and that named program
    object has a different target than the specified target parameter,
    the INVALID_OPERATION error is generated."

Additions to the EXT_gpu_program_parameters specification

    Add to the end of section 2.14.1 (Program Objects):

    "This command

        void NamedProgramLocalParameters4fvEXT(uint program, enum target,
                                               uint index, sizei count,
                                               const float *params); 

    operate identically to ProgramLocalParameters4fvEXT except, rather
    than updating the currently bound program for the program target
    parameter (a parameter not present for these listed commands), these
    "Named" commands update the program object named by the initial
    program parameter.  If the program parameter is zero, then the
    target parameter selects the default program of the specified target
    to update.  The remaining parameters following the initial program
    parameter for the listed "Named" commands match the parameters for
    the corresponding non-"Named" command and are interpreted as they
    are for the non-"Named" command.  If the program parameter is for
    an unused name, the name becomes used and the named program object
    is assigned target-specific default values (see section 2.14.7
    for vertex programs or section 3.11.8 for fragment programs), set
    to the same initial values prior to the command's state update.
    If the program parameter is for a used name and that named program
    object has a different target than the specified target parameter,
    the INVALID_OPERATION error is generated."

Additions to the NV_gpu_program4 specification

    Add to the end of section 2.14.1 (Program Objects):

    "These commands

        void NamedProgramLocalParameterI4iEXT(uint program, enum target,
                                              uint index, 
                                              int x, int y,
                                              int z, int w);
        void NamedProgramLocalParameterI4ivEXT(uint program, enum target,
                                               uint index,
                                               const int *params);
        void NamedProgramLocalParametersI4ivEXT(uint program, enum target,
                                                uint index, sizei count,
                                                const int *params);
        void NamedProgramLocalParameterI4uiEXT(uint program, enum target,
                                               uint index, 
                                               uint x, uint y,
                                               uint z, uint w);
        void NamedProgramLocalParameterI4uivEXT(uint program, enum target,
                                                uint index, 
                                                const uint *params);
        void NamedProgramLocalParametersI4uivEXT(uint program, enum target,
                                                 uint index, sizei count,
                                                 const uint *params);

    operate identically to the corresponding command where "Named"
    is deleted from the name (and extension suffixes are updated to
    NV appropriately) except, rather than updating the currently bound
    program for the program target parameter (a parameter not present for
    these listed commands), these "Named" commands update the program
    object named by the initial program parameter.  If the program
    parameter is zero, then the target parameter selects the default
    program of the specified target to update.  The remaining parameters
    following the initial program parameter for the listed "Named"
    commands match the parameters for the corresponding non-"Named"
    command and are interpreted as they are for the non-"Named" command.
    If the program parameter is for an unused name, the name becomes
    used and the named program object is assigned target-specific
    default values (see section 2.14.7 for vertex programs or section
    3.11.8 for fragment programs), set to the same initial values prior to
    the command's state update.  If the program parameter is for a used
    name and that named program object has a different target than the
    specified target parameter, the INVALID_OPERATION error is generated."

    Add to the end of section 6.1.12 (Program Queries):

    "These queries

        void GetNamedProgramLocalParameterIivEXT(uint program, enum target, uint index,
                                                 int *params);
        void GetNamedProgramLocalParameterIuivEXT(uint program, enum target, uint index,
                                                  uint *params);

    operate identically to the corresponding query where "Named" is
    deleted from the name (and extension suffixes are updated to NV
    appropriately) except, rather than querying the currently bound
    program for the program target parameter (a parameter not present for
    these listed query), these "Named" queries query the program object
    named by the initial program parameter.  If the program parameter
    is zero, then the target parameter selects the default program of
    the specified target to query.  The remaining parameters following
    the initial program parameter for the listed "Named" queries match
    the parameters for the corresponding non-"Named" query and are
    interpreted as they are for the non-"Named" query.  If the program
    parameter is for an unused name, the name becomes used and the named
    program object is assigned target-specific default values (see section
    2.14.7 for vertex programs or section 3.11.8 for fragment programs),
    set to the same initial values prior to the query's state query.
    If the program parameter is for a used name and that named program
    object has a different target than the specified target parameter,
    the INVALID_OPERATION error is generated."

Interactions with OpenGL 3.0 or the EXT_texture_integer specification

    If NEITHER OpenGL 3.0 nor EXT_texture_integer are supported, ignore
    the support for TextureParameterIivARB, TextureParameterIuivARB,
    GetTextureParameterIivARB, GetTextureParameterIuivARB,
    MultiTexParameterIivARB, MultiTexParameterIuivARB,
    GetMultiTexParameterIivARB, and GetMultiTexParameterIuivARB.

Interactions with the EXT_texture_buffer_object specification

    If EXT_texture_buffer_object is NOT supported, ignore the support
    for TextureBufferARB and MultiTexBufferARB.

Interactions with OpenGL 3.0 or the APPLE_vertex_array_object

    If NEITHER OpenGL 3.0 nor EXT_texture_integer are supported, ignore XXX

    If either OpenGL 3.0 or APPLE_vertex_array_object is supported, then
    ClientAttribDefaultARB also sets the VERTEX_ARRAY_BINDING vertex-array
    state to zero if the mask parameter has CLIENT_VERTEX_ARRAY_BIT set.

    This means PushClientAttribDefaultARB also sets the
    VERTEX_ARRAY_BINDING_APPLE vertex-array state to zero after pushing
    the client state.  if the mask parameter has CLIENT_VERTEX_ARRAY_BIT
    set.

Interactions with EXT_geometry_shader4 or NV_gpu_program4

    If both EXT_geometry_shader4 and NV_gpu_program4 are NOT
    supported, ignore the support for NamedFramebufferTextureARB,
    NamedFramebufferTextureLayerARB, and NamedFramebufferTextureFaceARB.

Interactions with OpenGL 3.0 or EXT_framebuffer_blit

    If NEITHER OpenGL 3.0 nor EXT_framebuffer_blit are supported,
    ignore the references to DRAW_FRAMEBUFFER and READ_FRAMEBUFFER in
    the discussion of CheckNamedFramebufferStatusARB and do not allow
    these tokens for the command's target parameter.

Interactions with OpenGL 3.0 or EXT_framebuffer_multisample

    If NEITHER OpenGL 3.0 or EXT_framebuffer_multisample are supported,
    ignore the support for NamedRenderbufferStorageMultisampleARB.

Interactions with NV_framebuffer_multisample_coverage

    If NV_framebuffer_multisample_coverage is NOT supported, ignore the
    support for NamedRenderbufferStorageMultisampleCoverageARB.

Interactions with the NV_explicit_multisample specification

    If NV_explicit_multisample is NOT supported, ignore the
    support for TextureRenderbufferARB, MultiTexRenderbufferARB,
    TEXTURE_BINDING_RENDERBUFFER_NV,
    and TEXTURE_RENDERBUFFER_DATA_STORE_BINDING_NV.

Interactions with the NV_texture_cube_map_array specification

    If NV_texture_cube_map_array is NOT supported, ignore the support
    for TEXTURE_BINDING_CUBE_MAP_ARRAY_NV.

Interactions with OpenGL 3.0

    If OpenGL 3.0 is NOT supported, ignore the support for
    EnableClientStateiEXT, DisableClientStateiEXT, GetFloati_vEXT,
    GetDoublei_vEXT, GetPointeri_vEXT, VertexArrayVertexOffsetEXT,
    VertexArrayColorOffsetEXT, VertexArrayEdgeFlagOffsetEXT,
    VertexArrayIndexOffsetEXT, VertexArrayNormalOffsetEXT,
    VertexArrayTexCoordOffsetEXT, VertexArrayMultiTexCoordOffsetEXT,
    VertexArrayFogCoordOffsetEXT, VertexArraySecondaryColorOffsetEXT,
    VertexArrayVertexAttribOffsetEXT,
    VertexArrayVertexAttribIOffsetEXT, EnableVertexArrayEXT,
    DisableVertexArrayEXT, EnableVertexArrayAttribEXT,
    DisableVertexArrayAttribEXT, GetVertexArrayIntegervEXT,
    GetVertexArrayPointervEXT, GetVertexArrayVertexAttribParameterivEXT,
    GetVertexArrayVertexAttribPointervEXT, MapNamedBufferRangeEXT,
    and FlushMappedNamedBufferRangeEXT.

    If OpenGL 3.0 is NOT supported, ignore references to Enablei,
    Disablei, IsEnabledi, GetBooleani_v, and GetIntegeri_v.

Additions to the AGL/GLX/WGL Specifications

    None.

GLX Protocol

    XXX incomplete!  ZZZZ values need to be registered!
    XXX ARB_vertex_program support is specified.

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

        NamedProgramLocalParameter4fvEXT
            2           36              rendering command length
            2           ZZZZ            rendering command opcode
            4           ENUM            program
            4           ENUM            target
            4           CARD32          index
            4           FLOAT32         params[0]
            4           FLOAT32         params[1]
            4           FLOAT32         params[2]
            4           FLOAT32         params[3]

        NamedProgramLocalParameter4dvEXT
            2           48              rendering command length
            2           ZZZZ            rendering command opcode
            4           ENUM            program
            4           ENUM            target
            4           CARD32          index
            8           FLOAT64         params[0]
            8           FLOAT64         params[1]
            8           FLOAT64         params[2]
            8           FLOAT64         params[3]

    The NamedProgramStringEXT is potentially large, and hence can be
    sent in a glXRender or glXRenderLarge request.

        NamedProgramStringEXT
            2           20+len+p        rendering command length
            2           ZZZZ            rendering command opcode
            4           ENUM            program
            4           ENUM            target
            4           ENUM            format
            4           sizei           len
            len         LISTofBYTE      program
            p                           unused, p=pad(len)

         If the command is encoded in a glxRenderLarge request, the command
         opcode and command length fields above are expanded to 4 bytes each:

            4           20+len+p        rendering command length
            4           ZZZZ            rendering command opcode

    The remaining commands are non-rendering commands.  These commands are
    sent separately (i.e., not as part of a glXRender or glXRenderLarge
    request), using the glXVendorPrivateWithReply request:

        GetNamedProgramLocalParameterfvEXT
            1           CARD8           opcode (X assigned)
            1           17              GLX opcode (glXVendorPrivateWithReply)
            2           6               request length
            4           ZZZZ            vendor specific opcode
            4           GLX_CONTEXT_TAG context tag
            4           ENUM            program
            4           ENUM            target
            4           CARD32          index
          =>
            1           1               reply
            1                           unused
            2           CARD16          sequence number
            4           m               reply length, m=(n==1?0:n)
            4                           unused
            4           CARD32          n (number of parameter components)

            if (n=1) this follows:

            4           FLOAT32         params
            12                          unused

            otherwise this follows:

            16                          unused
            n*4         LISTofFLOAT32   params

        GetNamedProgramLocalParameterdvEXT
            1           CARD8           opcode (X assigned)
            1           17              GLX opcode (glXVendorPrivateWithReply)
            2           6               request length
            4           ZZZZ            vendor specific opcode
            4           GLX_CONTEXT_TAG context tag
            4           ENUM            program
            4           CARD32          index
            4           ENUM            target
          =>
            1           1               reply
            1                           unused
            2           CARD16          sequence number
            4           m               reply length, m=(n==1?0:n*2)
            4                           unused
            4           CARD32          n (number of parameter components)

            if (n=1) this follows:

            8           FLOAT64         params
            8                           unused

            otherwise this follows:

            16                          unused
            n*8         LISTofFLOAT64   params

        GetNamedProgramivEXT
            1           CARD8           opcode (X assigned)
            1           17              GLX opcode (glXVendorPrivateWithReply)
            2           6               request length
            4           ZZZZ            vendor specific opcode
            4           GLX_CONTEXT_TAG context tag
            4           ENUM            program
            4           ENUM            target
            4           ENUM            pname
          =>
            1           1               reply
            1                           unused
            2           CARD16          sequence number
            4           m               reply length, m=(n==1?0:n)
            4                           unused
            4           CARD32          n

            if (n=1) this follows:

            4           INT32           params
            12                          unused

            otherwise this follows:

            16                          unused
            n*4         LISTofINT32     params

        GetNamedProgramStringEXT
            1           CARD8           opcode (X assigned)
            1           17              GLX opcode (glXVendorPrivateWithReply)
            2           6               request length
            4           ZZZZ            vendor specific opcode
            4           GLX_CONTEXT_TAG context tag
            4           ENUM            program
            4           ENUM            target
            4           ENUM            pname
          =>
            1           1               reply
            1                           unused
            2           CARD16          sequence number
            4           (n+p)/4         reply length
            4                           unused
            4           CARD32          n
            16                          unused
            n           STRING          program
            p                           unused, p=pad(n)

Errors

    All the commands in this extension excepting ClientAttribDefaultEXT
    are expressed in terms of existing GL commands and the error that
    apply to those commands apply to the new commands.  If an error
    occurs for any of the commands introduced by this extension, any
    selector used by the command is left undisturbed.

    Several errors are truly "new" with this extension:

    INVALID_OPERATION is generated by CopyTextureImage1DEXT,
    CopyTextureImage2DEXT, CopyTextureSubImage1DEXT,
    CopyTextureSubImage2DEXT, CopyTextureSubImage3DEXT,
    GetCompressedTextureImageEXT, GetTextureImageEXT,
    GetTextureLevelParameterfvEXT, GetTextureLevelParameterivEXT,
    GetTextureParameterfvEXT, GetTextureParameterIivEXT,
    GetTextureParameterIuivEXT, GetTextureParameterivEXT,
    TextureBufferEXT, TextureImage1DEXT, TextureImage2DEXT,
    TextureImage3DEXT, TextureParameterfEXT, TextureParameterfvEXT,
    TextureParameteriEXT, TextureParameterIivEXT, TextureParameterIuivEXT,
    TextureParameterivEXT, TextureSubImage1DEXT, TextureSubImage2DEXT,
    TextureSubImage3DEXT, and GenerateMultiTexMipmapEXT if the target
    parameter does not match the target type of the texture object named
    by the texture parameter.

    INVALID_OPERATION is generated by GetNamedBufferParameterivEXT,
    GetNamedBufferPointervEXT, GetNamedBufferSubDataEXT,
    MapNamedBufferEXT, NamedBufferDataEXT, NamedBufferSubDataEXT, and
    UnmapNamedBufferEXT if the buffer parameter is zero.

    INVALID_OPERATION is generated by ProgramUniform1fEXT,
    ProgramUniform2fEXT, ProgramUniform3fEXT, ProgramUniform4fEXT,
    ProgramUniform1iEXT, ProgramUniform2iEXT, ProgramUniform3iEXT,
    ProgramUniform4iEXT, ProgramUniform1fvEXT, ProgramUniform2fvEXT,
    ProgramUniform3fvEXT, ProgramUniform4fvEXT, ProgramUniform1ivEXT,
    ProgramUniform2ivEXT, ProgramUniform3ivEXT, ProgramUniform4ivEX,
    ProgramUniformMatrix2fvEXT, ProgramUniformMatrix3fvEXT,
    ProgramUniformMatrix4fvEXT, ProgramUniformMatrix2x3fv,
    ProgramUniformMatrix3x2fv, ProgramUniformMatrix2x4fv,
    ProgramUniformMatrix4x2fv, ProgramUniformMatrix3x4fv,
    ProgramUniformMatrix4x3fv, ProgramUniform1uiEXT, ProgramUniform2uiEXT,
    ProgramUniform3uiEXT, ProgramUniform4uiEXT, ProgramUniform1uivEXT,
    ProgramUniform2uivEXT, ProgramUniform3uivEXT, and
    ProgramUniform4uivEXT if the program named by the program parameter
    has not been successfully linked.

    INVALID_VALUE is generated by NamedProgramLocalParameter4dEXT,
    NamedProgramLocalParameter4dvEXT, NamedProgramLocalParameter4fEXT,
    NamedProgramLocalParameter4fvEXT, GetNamedProgramLocalParameterdvEXT,
    GetNamedProgramLocalParameterfvEXT, GetNamedProgramivEXT, and
    GetNamedProgramStringEXT if the program named by the program parameter
    does not exist.

    INVALID_OPERATION is generated by MultiTexCoordPointerEXT,
    VertexArrayMultiTexCoordOffsetEXT, MultiTexEnvfEXT, MultiTexEnvfvEXT,
    MultiTexEnviEXT, MultiTexEnvivEXT, MultiTexGendEXT, MultiTexGendvEXT,
    MultiTexGenfEXT, MultiTexGenfvEXT, MultiTexGeniEXT, MultiTexGenivEXT,
    MultiTexParameteriEXT, MultiTexParameterivEXT, MultiTexParameterfEXT,
    MultiTexParameterfvEXT, MultiTexParameterIivEXT,
    MultiTexParameterIuivEXT, MultiTexImage1DEXT, MultiTexImage2DEXT,
    MultiTexSubImage1DEXT, MultiTexSubImage2DEXT, CopyMultiTexImage1DEXT,
    CopyMultiTexImage2DEXT, CopyMultiTexSubImage1DEXT,
    CopyMultiTexSubImage2DEXT, MultiTexImage3DEXT, MultiTexSubImage3DEXT,
    CopyMultiTexSubImage3DEXT, MultiTexBufferEXT, GetMultiTexEnvfvEXT,
    GetMultiTexEnvivEXT, GetMultiTexGendvEXT, GetMultiTexGenfvEXT,
    GetMultiTexGenivEXT, GetMultiTexImageEXT, GetMultiTexParameterfvEXT,
    GetMultiTexParameterivEXT, GetMultiTexParameterIivEXT,
    GetMultiTexParameterIuivEXT, GetMultiTexLevelParameterivEXT,
    GetMultiTexLevelParameterfvEXT, and GetCompressedMultiTexImageEXT if
    the texunit parameter names a texture unit that is greater or equal in
    number to the implementations limit for maximum texture image units.

    INVALID_OPERATION is generated by FramebufferDrawBuffersEXT if a
    color buffer not currently allocated to the GL context is specified.

    INVALID_OPERATION is generated by FramebufferDrawBuffersEXT if <n>
    is greater than the state MAX_DRAW_BUFFERS.
    
    INVALID_OPERATION is generated by FramebufferDrawBuffersEXT if value
    in <bufs> does not correspond to one of the allowed buffers.

    INVALID_OPERATION is generated by FramebufferDrawBuffersEXT if a
    draw buffer other then NONE is specified more then once in <bufs>.

New State

    None.

New Implementation Dependent State

    None.

NVIDIA Implementation Details

    NVIDIA drivers prior to 330.00 (August 2013) have a bug where
    glMultiTexGeniEXT acts identically to glTexGeni (so glMultiTexGeniEXT
    ignores its texture unit parameter).
    
    As a workaround, use glMultiTexGenivEXT.  So problematic code written
    as:
    
      glMultiTexGeniEXT(texUnit, coord, pname, value);

    can be rewritten as:

      GLenum pvalue = value;
      glMultiTexGenivEXT(texUnit, coord, pname, &pvalue);

    NVIDIA drivers prior to 330.00 (August 2013) do not support
    the glEnableVertexArrayEXT and glDisableVertexArrayEXT with the
    GL_TEXTUREi tokens and instead generate a GL_INVALID_ENUM error.
    See issue 32.  The only workaround is to change the texture
    unit selector (glActiveTexture) and bind the vertex array
    object (glBindVertexArray) and call glEnable or glDisable with
    GL_TEXTURE_COORD_ARRAY.  Alternatively use generic vertex attribute
    arrays instead of texture coordinate arrays.

Issues

    (0) What is changed from version 1.0 to version 1.1 of this extension
        to support OpenGL 3.0?

        RESOLVED:  Changes are primarily cosmetic except the addition
        of API for selector-free access to vertex array objects since
        that functionality is part of OpenGL 3.0:

        1) Update all references to section numbering to OpenGL 3.0
        section numbers.

        2) Where EXT extensions have become part of OpenGL 3.0, refer
        to the functionality as part of OpenGL 3.0 rather than by
        extension name.

        3) New selector-free API for vertex buffer objects since these
        were introduced by OpenGL 3.0.  The EXT version specified
        a necessary glClientAttribDefaultEXT interaction with
        APPLE_vertex_buffer_object but didn't provide an selector-free
        API for vertex buffer objects.

        4) Add new selector-free API for fine control over mapping
        buffer subranges into client space (glMapNamedBufferRangeEXT)
        and flushing modified data (glFlushMappedNamedBufferRangeEXT).

        5) Add OpenGL 3.0-style aliases for the version 1.0 commands
        and queries that have "Indexed" in the name.  OpenGL 3.0 has a
        convention where an "i" indexed indexed commands and queries.
        For example, glGetFloati_v and glGetFloatIndexedvEXT are
        identical queries.  Likewise glEnableClientStateIndexedEXT and
        glEnableClientStateiEXT are identical commands.

    (1) What should this extension be called?

        RESOLVED: EXT_direct_state_access

        "direct" means state updates and queries are not indirected
        through a selector such as the matrix mode, active texture
        unit, active client texture unit, current texture binding,
        current vertex/fragment/geometry program, current GLSL program,
        or current buffer binding.

        "state" so there's not confusion about what this extension
        provides direct access to (not direct access to the hardware or
        the framebuffer, etc.).

        "access" is because this extension applies to both queries (reads)
        and updates (writes) of OpenGL state.  Access is general enough
        to encompass both queries and updates.

    (2) Should we have a "direct_state_access" extension for each type
        of OpenGL state involved (matrix, program, GLSL, texture unit,
        texture object) or have one uber-extension?  For example,
        EXT_direct_matrix_access, EXT_direct_texture_access, etc.

        RESOLVED: One uber-extension.

        This extension introduces no additional hardware functionality
        but rather provides commands to perform state updates and queries
        without having to change (and possibly query and restore) API
        selectors.

        The dependencies sections make it clear that if some functionality
        (say, GLSL) is not supported, implementations supporting this
        extension ignore the direct access API for the particular missing
        functionality.

        This simplifies the burden on applications to use the new direct
        access API.  When this extension is supported, the application can
        assume all functionality supported by their respective extensions
        is available through the direct access commands introduced by
        this extension.

    (3) Explain the methodology for naming selector-free commands.

        The naming conventions seek to maximize consistency but
        differences between the various selectors and command subsets
        dictate differences in approach.

        The chosen naming conventions has two guiding principles: 1)
        making the selector-free commands similar to the existing
        selector-based commands in naming but also clearly and
        consistently distinguished (at least within each group of
        commands) from the existing selector-based commands to which
        selector-free commands correspond by a simple pattern, and 2)
        being conscious of the length in characters of the resulting
        command names.

        Selector-less matrix commands all start glMatrix* (rather than gl*
        or gl*Matrix[fd] for the corresponding selector-based commands).

        Rationale: The selector-based matrix commands have the
        classic verb-noun format (example: glLoadMatrixf) described
        in Kurt Akeley's "Syntax Rules for OpenGL Extensions" document
        (henceforth abbreviated SRfOE) while the selector-free versions
        have a noun-verb format.  This variance from SRfOE conventions
        is deemed warranted for the sake of consistent naming of all the
        selector-free matrix commands.

        The alternative of using "NamedMatrix" as a suffix to the
        matrix commands was considered (example: glLoadNamedMatrixf
        rather than glLoadMatrixf) but most matrix commands do not
        contain the word Matrix so this leads to awkward constructions
        such as glFrustumNamedMatrix and glLoadIdentityNamedMatrix.
        glMatrixFrustum and glMatrixLoadIdentity were preferred despite
        the variance this creates with SRfOE.  Also considered was
        adding "Named" or "NamedMatrix" as a prefix to the matrix
        commands (example: glNamedLoadMatrixf, glNamedFrustum,
        glNamedLoadIdentity; or glNamedMatrixLoadMatrixf,
        glNamedMatrixFrustum, glNamedMatrixLoadIdentity).  But the
        "Named" prefix is awkward because it is not the frustum,
        etc. that is named but rather a matrix.  The "NamedMatrix" prefix
        becomes awkward because of the length of the resulting commands
        while having a noun-verb format.  The "Matrix" prefixed format
        (where "Matrix" appears in the command name only once) provides
        consistency of naming and minimizes command name length but
        at the consistency cost of varying with the SRfOE's verb-noun
        convention.

        Selector-less texture object commands all start glTexture*
        or glGetTexture* (rather than glTex* and glGetTex* for the
        corresponding selector-based commands).

        Rationale: SRfOE states "Tex" is an abbreviation for "Texture"
        in command names.  However in the context of texture objects, the
        abbreviated "Texture" is used instead (example: glIsTexture,
        not glIsTex).  The abbreviation "Tex" is used when texture is
        used as an adjective to describe state being specified (examples:
        glTexParameter* and glTexImage*).  The unabbreviated "Texture"
        is used as a noun in command names.

        The selector-free texture object commands use the unabbreviated
        "Texture" as an adjective since a texture object is accessed
        directly where the "Tex" commands refer to texture state accessed
        indirectly based on the currently bound texture object.

        Selector-less multitexture texture unit commands and queries
        all replace "Tex" with "MultiTex"  and a new initial texunit
        identifies the texture unit by token (mimicking how TexCoord2f
        is MultiTexCoord2f for multitexture immediate mode).

        Selector-less generic enables (glEnable, glDisable)
        for texture unit enables make use of the convention for
        indexed queries introduced by EXT_draw_buffers2 and also
        used by EXT_transform_feedback so use glEnableIndexedEXT and
        glDisableIndexedEXT.

        Selector-less generic queries (glGetIntegerv, glGetFloatv,
        glGetPointerv, etc) for texture unit state make use
        of the convention for indexed queries introduced by
        EXT_draw_buffers2 and also used by EXT_transform_feedback so use
        glGetIntegerIndexedvEXT, glGetFloatIndexedvEXT,
        glGetDoubleIndexedvEXT, glGetBooleanIndexedvEXT, and
        glIsEnabledIndexedEXT.

        OpenGL 3.0 introduced a new naming convention for indexed
        state enables and queries so glGetIntegeri_v, glGetFloati_vEXT,
        glGetDoublei_vEXT, and glGetBooleani_v, glIsEnabledi operate
        identically respectively to the prior indexed query list.

        Selector-less buffer object commands all start with glNamedBuffer
        or glGetNamedBuffer.

        Selector-less program parameter commands (for
        ARB_vertex_program-based extensions) all start glNamedProgram
        or glGetNamedProgram.

        Selector-less uniform commands for GLSL all start glProgramUniform.

        Selector-less framebuffer object commands all start
        with glNamedFramebufer, glGetNamedFramebuffer, or
        glCheckNamedFramebuffer.  The selector-less framebuffer
        control commands are glFramebufferDrawBufferEXT,
        glFramebufferDrawBuffersEXT, and glFramebufferReadBufferEXT.

        Selector-less renderbuffer object commands all start
        with glNamedRenderbuffer or glGetNamedRenderbuffer.

    (4) Should the selector-free glTexture* and glNamedProgram* commands
        and glGetTexture* and glGetNamedProgram* queries have target
        parameters (for passing GL_TEXTURE_2D or GL_VERTEX_PROGRAM_ARB,
        etc.)?

        RESOLVED:  Yes.

        It would be desirable to update a texture parameter for a given
        texture object without having to know the target of the texture
        object.  For example, one could change the GL_TEXTURE_MIN_FILTER
        of a texture object without knowing if the texture object was
        a 1D, 2D, 3D, or cube map texture.

        As desirable as that might be, OpenGL's texture target scheme
        makes that difficult in general for several reasons.

        First, a side-effect of glBindTexture is that a texture object of
        the indicated target is created if the specified texture object
        name does not map to an existent texture object.  In this case,
        a texture object of the specified target is created and its state
        is initialized to the initial texture object state based on the
        specified target.  The selector-free texture object commands
        should operate the same way if a non-existent texture object
        is specified.

        Second, cube maps have face-specific targets
        (GL_TEXTURE_CUBE_MAP_POSITIVE_X, etc.) as well as the
        face-independent target (GL_TEXTURE_CUBE_MAP).  Commands for
        texture image specification (glTexImage2D, etc.) and query
        (glGetTexImage) require the target parameter to select the
        appropriate face.

        Assembly program commands have a similar need for a target
        parameter.  Calling glBindProgramARB is specified to create an
        empty program of the specified target type of the bind.

        Semantically, glTexture* commands (and glGetTexture* queries) are
        semantically equivalent of performing a glBindTexture followed
        atomically by the equivalent glTex* command (or equivalent
        glGetTex* query).

        Likewise semantically, glNamedProgram* commands (and
        glGetNamedProgram* queries) are semantically equivalent of
        performing a glBindProgramARB followed atomically by the
        equivalent glProgram* command (or equivalent glGetProgram* query).

        Note that buffer commands do not have this same need for a target
        parameter in their selector-less form.

    (5) The OpenGL API has "latched" state.  Explain latched state
        and how this extension addresses latched state.

        RESOLVED:  Examples of latched state in the OpenGL API are the
        current array and array element buffers and the pixel store
        pack/unpack state.  Latched stated is all client-side state
        (pixel store or vertex array).

        The state of the current array buffer acts as an extra parameter
        to all the gl*Pointer calls to configure vertex arrays.  The state
        of the current element array buffer acts as an extra parameter to
        the glDrawElements family of commands.  The pixel store unpack
        state acts as a collection of extra parameters to glTexImage*,
        glTexSubImage*, glDrawPixels, glBitmap, glColorTable,
        glPolygonStipple, glConvolutionFilter*, etc.  The pixel store pack
        state acts as a collection of extra parameters to glReadPixels,
        glGetTexImage, glGetColorTable, etc.

        Whereas a selector is an extra parameter that designates what
        state variable is to be updated or queried, latched state is
        actual state values the command uses to update other state
        variables or control the operation of the command.

        Latched state is similar in its undesirability for layered
        libraries because it requires OpenGL state variables to be
        modified to update particular state variables or control the
        operation of the command.

        Fixing the latched state problem with additional API is involved
        because it would require introducing a new command for every
        existing OpenGL command accepting a pointer to specify vertex
        arrays or pixel data or transform feedback buffer with a "uint
        buffer, intptr offset" set of parameters rather than a pointer.

        This extension addresses latched state by adding a new command
        glClientAttribDefaultEXT that uses its mask parameter to set all
        the client vertex array or pixel store state to its default state.

        The glPushClientAttribDefaultEXT performs the
        glClientAttribDefaultEXT in combination with a glPushClientAttrib
        command.  This provides an inexpensive way to save-and-restore the
        latched client state so layered libraries that want well-defined
        latched client state can use these commands.

        Because the state affected by glPushClientAttribDefaultEXT
        and glClientAttribDefaultEXT is all client-side, this state
        is inexpensive to update (unlike the glPushAttrib/glPopAttrib
        commands).

        Some consideration was given to providing extra mask bits to
        control just the vertex array enables (to disable them all) or
        pixel store pack and unpack state independently (just the pack
        or just the unpack state).  The entire set of vertex array and
        pixel store state is compact enough that it doesn't make sense
        to add extra mask bits for subsets of the state.

    (6) How is the expense of a per-command specified texture object,
        assembly program object, buffer object, or GLSL program object
        name lookup minimized?

        RESOLVED:  Modern OpenGL driver implementations implementing
        this extension are expected to cache most recently used object
        names so accessing the last name repeatedly is fast.

        The details of this is left up to the OpenGL implementation but
        developers can expect consecutive direct access commands to the
        same named object will be efficient.

    (7) What should the selector-free glBindTexture routine be called?

        RESOLVED: glBindMultiTextureEXT

        This name shares the same "Multi" subword with the other routines
        (glMultiTexGen*, glMultiTexEnv*, glMultiTexParameter*, etc.).

        The name uses "MultiTexture" instead of simply "MultiTex" because
        the glBindMultiTextureEXT command takes a texture object parameter
        (hence "Texture" instead of "Tex" used for texture unit-based
        commands) as well as a texture unit parameter.

    (8) Should glGetIntegeri_v, glGetIntegerIndexedvEXT, glIsEnabledi,
        glIsEnabledIndexedEXT, etc. work of all query tokens or just
        query tokens for indexed state such as query tokens where the
        active texture or client active texture apply?

        RESOLVED: Just for query tokens for indexed state.

        This is consistent with how EXT_draw_buffers2 and
        EXT_transform_feedback work for their Indexed commands.

        How the index parameter is interpreted depends on the queried state.
        For texture related state the index refers to the active texture unit
        or active client texture unit appropriately.

        Said index texture tokens are:

            GL_CURRENT_MATRIX_NV
            GL_CURRENT_MATRIX_STACK_DEPTH_NV
            GL_CURRENT_RASTER_TEXTURE_COORDS
            GL_CURRENT_TEXTURE_COORDS
            GL_TEXTURE_BINDING_1D
            GL_TEXTURE_BINDING_1D_ARRAY
            GL_TEXTURE_BINDING_2D
            GL_TEXTURE_BINDING_2D_ARRAY
            GL_TEXTURE_BINDING_3D
            GL_TEXTURE_BINDING_BUFFER_EXT
            GL_TEXTURE_BINDING_CUBE_MAP
            GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_NV
            GL_TEXTURE_BINDING_RECTANGLE_ARB
            GL_TEXTURE_BUFFER_DATA_STORE_BINDING_EXT
            GL_TEXTURE_BUFFER_FORMAT_EXT
            GL_TEXTURE_COORD_ARRAY
            GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING
            GL_TEXTURE_COORD_ARRAY_COUNT
            GL_TEXTURE_COORD_ARRAY_POINTER
            GL_TEXTURE_COORD_ARRAY_SIZE
            GL_TEXTURE_COORD_ARRAY_STRIDE
            GL_TEXTURE_COORD_ARRAY_TYPE
            GL_TEXTURE_GEN_Q
            GL_TEXTURE_GEN_R
            GL_TEXTURE_GEN_S
            GL_TEXTURE_GEN_T
            GL_TEXTURE_MATRIX
            GL_TEXTURE_STACK_DEPTH
            GL_TRANSPOSE_TEXTURE_MATRIX
            GL_TEXTURE_1D
            GL_TEXTURE_2D
            GL_TEXTURE_3D
            GL_TEXTURE_CUBE_MAP
            GL_TEXTURE_RECTANGLE_ARB

        For EXT_draw_buffers2 or EXT_transform_feedback queries, the
        index refers to the draw buffer or transform feedback buffer
        appropriately.

    (9) Why does the equivalent code for glGetIntegeri_v,
        glGetIntegerIndexedvEXT, glIsEnabledi, glIsEnabledIndexedEXT,
        etc. save and restore the active texture and client active
        texture state appropriately?

        RESOLVED:  Most query tokens use the active texture but some
        (those starting with GL_TEXTURE_COORD_ARRAY involving vertex
        arrays) use the client active texture.

        For historical reasons, glEnable/glDisable can be used to
        enable/disable client state that would be better enabled/disabled
        with glEnableClientState/glDisableClientState.

        The appropriate selector (active texture or client active texture)
        is saved or restored based on the query target.

   (10) Can these selector-free state update commands be compiled into
        display lists?

        RESOLVED:  YES

        The object name, texture unit, or matrix mode parameter is
        compiled into the display list by-value like any other value
        parameter.

        This capability to compile selector-free commands into display
        lists is one of the significant benefits of this extension.
        Prior to this extension, the only reliable way to update
        state for a particular texture unit, matrix, buffer, or
        texture without disturbing OpenGL selector state was using
        glPushAttrib/glPopAttrib which is too expensive to be practical.

        However the glGet* selector-free commands, being queries, cannot
        be compiled into display lists.

   (11) Why are there no glGetProgramUniform* query commands for GLSL?

        RESOLVED:  OpenGL 2.0 already has glGetUniform* query commands
        that accept a program parameter as a parameter so are already
        selector-free.

   (12) Is glMatrixLoadfEXT(GL_TEXTURE, matrixData), etc. legal?

        RESOLVED:  YES.

        This will update the texture matrix based on the current active
        texture.  This avoids the matrix mode selector but still relies
        on the active texture selector.

        Use GL_TEXTUREn where n is the texture unit to reference a
        specific texture unit's texture matrix without changing either
        the matrix mode or active texture state.

   (13) Some glTex* and glGetTex* routines accept proxy targets.  How do
        proxy textures work with the selector-free commands?

        RESOLVED:  Proxy targets work with the glTex* (glTexImage*)
        and glGetTex* (glGetTexLevelParameter*) commands that support
        proxy textures BUT the texture name must be 0 to avoid a
        GL_INVALID_OPERATION error.

        This is a consequence of the requirement that the target parameter
        must match the target of the named texture object.

        Only the texture object name zero (which exists for all the
        supported texture targets, including proxies) exists as a
        proxy target.

        This should work:

          GLuint texobj = 0;
          GLint width;
          glTexureImage2D(texobj, GL_PROXY_TEXTURE_2D,
                          0, GL_RGB, 32, 32, 0, GL_RGB,
                          GL_UNSIGNED_BYTE, image);
          glGetTextureLevelParameterivEXT(texobj, GL_PROXY_TEXTURE_2D,
                                          GL_TEXTURE_WIDTH, &width)
          if (width > 0) {
             // 32x32 RGB texture supported by implementation
          } else {
             // 32x32 RGB texture NOT supported by implementation
          }

        This same code would generate a GL_INVALID_OPERATION error if
        texobj was a non-zero value.

   (14) What does glClientAttribDefaultEXT(GL_CLIENT_PIXEL_STORE_BIT) do?

        RESOLVED:  It is equivalent to:

          glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
          glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
          glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
          glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0);
          glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
          glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
          glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
          glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
          glPixelStorei(GL_PACK_SWAP_BYTES, GL_FALSE);
          glPixelStorei(GL_PACK_LSB_FIRST, GL_FALSE);
          glPixelStorei(GL_PACK_IMAGE_HEIGHT, 0);
          glPixelStorei(GL_PACK_SKIP_IMAGES, 0);
          glPixelStorei(GL_PACK_ROW_LENGTH, 0);
          glPixelStorei(GL_PACK_SKIP_ROWS, 0);
          glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
          glPixelStorei(GL_PACK_ALIGNMENT, 4);

          glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
          glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);

        Note both the pack and unpack state are set to their initial
        values.

        Keep in mind that the initial unpack/pack alignment of 4, while
        the specified initial value, is often surprising to OpenGL
        developers who expect the alignment to be 1.

   (15) What does glClientAttribDefaultEXT(GL_CLIENT_VERTEX_ARRAY_BIT) do?

        RESOLVED:  It is equivalent to:

          int i;
          GLint max;

          glBindBuffer(GL_ARRAY_BUFFER, 0);
          glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

          glDisableClientState(GL_EDGE_FLAG_ARRAY);
          glEdgePointer(0, 0);

          glDisableClientState(GL_INDEX_ARRAY);
          glIndexPointer(GL_FLOAT, 0, 0);

          glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
          glSecondaryColorPointer(4, GL_FLOAT, 0, 0);

          glDisableClientState(GL_FOG_COORD_ARRAY);
          glFogCoordPointer(GL_FLOAT, 0, 0);

          glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max);
          for (i=0; i<max; i++) {
            glClientActiveTexture(GL_TEXTURE0 + i);
            glDisableClientState(GL_TEXTURE_COORD_ARRAY);
            glTexCoordPointer(4, GL_FLOAT, 0, 0);
          }

          glDisableClientState(GL_COLOR_ARRAY);
          glColorPointer(4, GL_FLOAT, 0, 0);

          glDisableClientState(GL_NORMAL_ARRAY);
          glNormalPointer(GL_FLOAT, 0, 0);

          glDisableClientState(GL_VERTEX_ARRAY);
          glVertexPointer(4, GL_FLOAT, 0, 0);

          glDisableClientState(GL_WEIGHT_ARRAY_ARB);
          glWeightPointerARB(0, GL_FLOAT, 0, 0);

          glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &max);
          for (i=0; i<max; i++) {
            glDisableVertexAttribArray(i);
            glVertexAttribPointer(i, 4, GL_FLOAT, GL_FALSE, 0, 0);
          }

          glClientActiveTexture(GL_TEXTURE0);

        Keep in mind the initial state of the vertex array enable
        is disabled.  Applications will typically at least
        want glEnableClientState(GL_VERTEX_ARRAY) called after
        glClientAttribDefaultEXT(GL_CLIENT_VERTEX_ARRAY_BIT) for this
        reason.

   (16) Should glGetFloatIndexedvEXT and glGetDoubleIndexedvEXT return
        values for non-texture state parameters similar to the parameters
        that work for glGetIntegerIndexedvEXT and glGetBooleanIndexedvEXT
        that EXT_draw_buffers2, EXT_transform_feedback, and
        NV_transform_feedback support?

        RESOLVED:  glGetFloatIndexedvEXT and glGetDoubleIndexedvEXT
        should accept without error parameter tokens supported
        by glGetIntegerIndexedvEXT and glGetBooleanIndexedvEXT
        through the EXT_draw_buffers2, EXT_transform_feedback, and
        NV_transform_feedback extensions.  In these cases, GLfloat or
        GLdouble values respectively of the indexed state should be
        returned.

        The EXT_draw_buffers2 extension specifically considered adding
        glGetFloatIndexedvEXT and glGetDoubleIndexedvEXT queries but
        left them out since none of the indexed state introduced was
        floating-point.  This extension adds floating-point indexed state
        and so adds glGetFloatIndexedvEXT and glGetDoubleIndexedvEXT
        and thereby enhances the functionality of these unrelated
        extensions supporting glGetIndexedv, etc. by introducing
        glGetFloatIndexedvEXT and glGetDoubleIndexedvEXT and expecting
        them to operate consistently with glGetIntegerIndexedvEXT except
        returning GLfloat and GLdouble versions of the queried state
        respectively.

        Following the OpenGL 3.0 function naming convention for indexed
        state, version 1.1 of this specification adds glGetFloati_vEXT
        and glGetDoublei_vEXT queries.

   (17) Should there be a selector-free way to query the "program"
        matrices introduced by ARB_vertex_program?

        RESOLVED:  Yes.  The GL_PROGRAM_MATRIX_EXT,
        GL_TRANSPOSE_PROGRAM_MATRIX_EXT, and
        GL_PROGRAM_MATRIX_STACK_DEPTH_EXT tokens supported by
        glGetFloati_vEXT, glGetFloatIndexedvEXT, etc. query the program
        matrices specified by GL_MATRIX0_ARB, etc.

        The ARB_vertex_program (and NV_vertex_program) introduced the
        GL_CURRENT_MATRIX_ARB, GL_TRANSPOSE_CURRENT_MATRIX_ARB, and
        GL_CURRENT_MATRIX_STACK_DEPTH_ARB query tokens to get back the
        current matrix based on the glMatrixMode state.  This avoided
        adding a large set of tokens to query the matrix, transpose
        matrix, and matrix stack depth for all the program matrices.
        But this made querying these matrices always dependent on the
        matrix mode selector.  The indexed glGet queries are allow
        indexed access to the program matrices but the above new query
        tokens must be added for this purpose.

   (18) How does this extension interact with APPLE_vertex_array_object?

        RESOLVED:  The VERTEX_ARRAY_BINDING_APPLE state is
        client vertex-array state so glClientAttribDefaultEXT and
        glPushClientAttribDefaultEXT should, when their mask parameter has
        CLIENT_VERTEX_ARRAY_BIT set, set the VERTEX_ARRAY_BINDING_APPLE
        state to its initial value of zero.

        This could go unsaid if the APPLE_vertex_array_object
        specification explicitly listed the VERTEX_ARRAY_BINDING_APPLE
        state in one of tables 6.6, 6.7, and 6.8.

   (19) glGetProgramivARB queries per-program state corresponding to
        the current program for the specified target but also queries
        per-target state.  Should glGetNamedProgramivEXT return
        only per-program state and not per-target state?  Or should
        glGetNamedProgramivEXT return both per-program and per-target
        state?

        RESOLVED:  glGetNamedProgramivEXT should accept the same pname
        parameters as glGetProgramivARB and thus should handle BOTH
        per-program AND per-target queries.

        However glGetNamedProgramivEXT does require the specified
        program object's target must match the specified (supported)
        target parameter otherwise an INVALID_OPERATION error occurs.
        Program object zero applies to all program targets so specifying
        program object zero avoids the possibility of this error.

        This resolution avoids having to keep a list of allowed
        per-program vs. disallowed per-target tokens up-to-date with
        future extensions.

        The ARB_vertex_program and ARB_fragment_program per-target
        program query tokens are GL_PROGRAM_BINDING_ARB,
        GL_MAX_PROGRAM_ENV_PARAMETERS_ARB,
        GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB,
        GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB,
        GL_MAX_PROGRAM_INSTRUCTIONS_ARB,
        GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB,
        GL_MAX_PROGRAM_TEMPORARIES_ARB,
        GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB,
        GL_MAX_PROGRAM_PARAMETERS_ARB,
        GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB, GL_MAX_PROGRAM_ATTRIBS_ARB,
        GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB,
        GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB,
        GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB,
        GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB,
        GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB,
        GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB,
        GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB,
        GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB,
        GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV, GL_MAX_PROGRAM_CALL_DEPTH_NV,
        GL_MAX_PROGRAM_IF_DEPTH_NV, GL_MAX_PROGRAM_LOOP_DEPTH_NV,
        GL_MAX_PROGRAM_LOOP_COUNT_NV.  The NV_gpu_program4
        extension adds GL_MAX_PROGRAM_ATTRIB_COMPONENTS_NV,
        GL_MAX_PROGRAM_RESULT_COMPONENTS_NV,
        GL_MAX_PROGRAM_GENERIC_ATTRIBS_NV,
        GL_MAX_PROGRAM_GENERIC_RESULTS_NV,
        GL_MAX_PROGRAM_OUTPUT_VERTICES_NV and
        GL_MAX_PROGRAM_TOTAL_OUTPUT_COMPONENTS_NV.
        The NV_parameter_buffer_object extension adds
        GL_MAX_PROGRAM_PARAMETER_BUFFER_BINDINGS_NV and
        GL_MAX_PROGRAM_PARAMETER_BUFFER_SIZE_NV.

        The ARB_vertex_program and ARB_fragment_program per-program
        program query tokens are GL_PROGRAM_LENGTH_ARB,
        GL_PROGRAM_FORMAT_ARB, GL_PROGRAM_INSTRUCTIONS_ARB,
        GL_PROGRAM_TEMPORARIES_ARB, GL_PROGRAM_PARAMETERS_ARB,
        GL_PROGRAM_ATTRIBS_ARB, GL_PROGRAM_ADDRESS_REGISTERS_ARB,
        GL_PROGRAM_ALU_INSTRUCTIONS_ARB, GL_PROGRAM_TEX_INSTRUCTIONS_ARB,
        GL_PROGRAM_TEX_INDIRECTIONS_ARB,
        GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB,
        GL_PROGRAM_NATIVE_TEMPORARIES_ARB,
        GL_PROGRAM_NATIVE_PARAMETERS_ARB, GL_PROGRAM_NATIVE_ATTRIBS_ARB,
        GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB,
        GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB,
        GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB,
        GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB, and
        GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB.
        The NV_gpu_program4 extension adds GL_GEOMETRY_VERTICES_OUT_EXT,
        GL_GEOMETRY_INPUT_TYPE_EXT, GL_GEOMETRY_OUTPUT_TYPE_EXT,
        GL_PROGRAM_ATTRIB_COMPONENTS_NV, and
        GL_PROGRAM_RESULT_COMPONENTS_NV.

   (20) When multiple contexts are sharing objects such as textures,
        programs, and/or buffers what expectations exist for when other
        contexts will see the state updates to textures, programs,
        and buffers manipulated by this extension?

        RESOLVED:  This extension doesn't change the expected semantics
        for multiple context sharing objects within a share group, but
        this is an appropriate place to document these expectations for
        both developers and implementers.

        Object state updates are visible in two ways:  1) queries return
        the current (most recently updated) state, and 2) rendering
        results are affected by the updated state.

        When a context updates objects, that updating context must observe
        those updates immediately for both queries and rendering results.
        This is a strong requirement for "sequential consistency" of
        updates and queries based on the context's own sequential stream
        of commands and queries.

        Queries by other OpenGL rendering contexts in the same share
        group with a context updating some shared OpenGL object must
        observe the effect of another context's update with "transactional
        consistency".  Program state updates and queries are treated as
        "transactions" that must be consistent with some serialized order.
        Implementations typically achieved this by guaranteeing mutual
        exclusion for all object updates and queries.  This is a strong
        consistency requirement.

        Rendering results based on updated state are subject to a
        weaker consistency requirement.  Rendering results by other
        OpenGL rendering contexts in the same share group with a context
        updating some shared OpenGL object may see a stale version of
        the object's state if the those contexts sharing the object are
        bound to the object when the state update occurs.

        Even so, the stale values of the object's state must always
        represent a consistent state of the object transactionally
        consistent when the object was last "bound" or otherwise used
        for rendering.  We refer to this weaker consistency as "bind
        consistency".

        This requirement means, for example, a texture object should NEVER
        observe the red and green components to be from one state update
        while the red and alpha components correspond to a subsequent
        state update.

        A context other than the context performing an update is
        guaranteed to see a "transactional consistent" view of an
        object's state when the context next processes a command to bind
        or otherwise "use" an object for rendering.  However if the
        object being updated is currently bound or "used" by another
        context, when this update is observed is not well-defined.
        So to guarantee an up-to-date version of a bound object's state,
        the context must re-bind to the updated object.

        (UNRESOLVED:  Should a re-bind require binding to a different
        object and then binding back to the object, or is simply rebinding
        to the same name already bound enough?  As a performance
        optimization, an OpenGL implementation may treat binding to
        an already bound object as a no-op.  However it would be nice
        if binding to any already bound object at least checked if the
        object had been updated since the last bind and, if an update
        has occurred, update the context's view of the object used for
        rendering.)

        Some examples (with serialized order shown):

        Sequential consistency for one thread:

            thread A:
                glBindMultiTextureEXT(GL_TEXTURE1, GL_TEXTURE_2D, 23);
                glEnablei(GL_TEXTURE_2D, 1);
                glTextureParameterivEXT(23, GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
                glDrawElements(...); // first render
                glTextureParameterivEXT(23, GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
                glDrawElements(...); // second render

        The first render must observer texture 23 using GL_LINEAR
        minification filtering while the second render must observe
        GL_NEAREST minification filtering.

        Transactional consistency for queries by multiple sharing
        contexts:

            thread A:
                glTextureParameteriv(23, GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
                glGetTextureParameteriv(23, GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, &geti1);
            thread B:
                glTextureParameteriv(23, GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
            thread A:
                glGetTextureParameteriv(23, GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, &geti2);

        geti1 should return GL_LINEAR bug geti2 should return GL_NEAREST.

        Bind consistency for rendering by multiple sharing contexts:

            thread A:
                glBindMultiTextureEXT(GL_TEXTURE1, GL_TEXTURE_2D, 23);
                glEnablei(GL_TEXTURE_2D, 1);
                glTextureParameterivEXT(23, GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            thread B:
                glTextureParameterivEXT(23, GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
            thread A:
                glDrawElements(...); // first render
                glBindMultiTextureEXT(GL_TEXTURE1, GL_TEXTURE_2D, 23);
                glDrawElements(...); // second render

        The first render may or may not observe the minification
        filter be set to GL_NEAREST; an implementation could use the
        stale GL_LINEAR state.  The second render should observe the
        minification filter be set to GL_NEAREST.

        Perhaps a bind away might be required for consistency, binding
        away from 23, then back to 23:

            thread A:
                glBindMultiTextureEXT(GL_TEXTURE1, GL_TEXTURE_2D, 0);
                glBindMultiTextureEXT(GL_TEXTURE1, GL_TEXTURE_2D, 23);
                glDrawElements(...); // second render

   (20) Should direct access commands and queries be added for
        renderbuffer and framebuffer objects?

        RESOLVED:  Yes.

        These should be added for completeness.

   (21) Should the Named framebuffer and renderbuffer object commands take
        a target parameter in addition to the initial GLuint
        framebuffer/renderbuffer parameter?

        RESOLVED:  No, except for CheckNamedFramebufferStatusEXT (see
        the next issue).

        The rationale for including a target parameter for the texture
        commands is that the default texture object zero and cube map
        face targets need the target for disambiguation.

        Likewise assembly programs needs a target parameter to know
        how source text should be parsed, etc.  Programs really have
        different target types (vertex, geometry, fragment).

        Buffer objects do not include a target parameter in their Named
        commands because the target identifies the binding point for the
        buffer while buffers themselves do not have a target type so the
        target is relevant for binding buffers, but not accessing buffers.

        The only legal values for target or RENDERBUFFER and
        FRAMEBUFFER respectively so there is really one type of
        renderbuffer and framebuffer respectively.

        The target parameter could be used by future extensions but
        so far the several extensions that extend framebuffer and
        renderbuffer objects already (EXT_framebuffer_multisample,
        NV_framebuffer_multisample_coverage, EXT_geometry_shader4,
        and NV_gpu_program4) maintain a single legal framebuffer and
        renderbuffer target value.

        This does not preclude new binding targets for renderbuffer or
        framebuffers in the way buffer objects support lots of binding
        targets but buffers themselves are target-free (unlike textures
        and programs).

   (22) How should the target parameter work for
        glCheckNamedFramebufferStatusEXT?

        RESOLVED:  The target parameter determines whether the status
        check is for reading or drawing.

        OpenGL 3.0 (by incorporating the EXT_framebuffer_blit extension)
        introduces GL_DRAW_FRAMEBUFFER and GL_READ_FRAMEBUFFER targets.
        A framebuffer object may be supported for drawing but perhaps
        not reading (or vice versa).  glCheckNamedFramebufferStatusEXT
        uses its target parameter to determine whether the check is for
        reading or writing.

        Because glCheckFramebufferStatus allows for "an
        implementation-dependent set of restrictions" for
        which GL_FRAMEBUFFER_UNSUPPORTED may be returned,
        it is possible for glCheckNamedFramebufferStatusEXT
        to return GL_FRAMEBUFFER_COMPLETE when binding to
        the framebuffer object with glBindFramebuffer and
        then calling glCheckFramebufferStatus may generate
        GL_FRAMEBUFFER_COMPLETE may be returned, it is possible
        for glCheckNamedFramebufferStatusEXT could return still return
        GL_FRAMEBUFFER_UNSUPPORTED.

        Despite this allowance, the intent here however is that an
        application should be able to create a framebuffer object and
        determine in most cases that a framebuffer object can be supported
        with glCheckNamedFramebufferStatusEXT.

   (23) Do we need glFramebufferDrawBufferEXT, glFramebufferDrawBuffersEXT
        and glFramebufferReadBufferEXT commands?

        UNRESOLVED:  Yes, add them.

        The READ_BUFFER and DRAW_BUFFER state is per-framebuffer object
        and glDrawBuffers, glReadBuffer, and glDrawBuffer update the
        currently bound framebuffer object.  These commands use the
        current framebuffer object binding as a selector so there should
        be selector-free versions of this commands.

        Since these commands didn't have Framebuffer in the name before,
        we avoid saying "NamedFramebuffer" in the commands.

   (24) Should there be a selector-free way to query the Framebuffer
        Dependent Values (table 9.nnn) for a named framebuffer object?

        RESOLVED:  No.

        It makes sense to provide selector-free queries for API-settable
        state such as GL_READ_BUFFER, GL_DRAW_BUFFER, and GL_DRAW_BUFFERi
        but framebuffer dependent values of a framebuffer object state
        are really derived state value and depends on the status of a
        framebuffer object bind.

        OpenGL 3.0 (by incorporating the EXT_framebuffer_object)
        describes per-framebuffer object state in its tables 4.nnn
        and 9.nnn.  The framebuffer object API allows this state to be
        queried with glGetIntegerv, etc. based on the current framebuffer
        object binding (a selector).  The glGetFramebufferParameteriv
        command queries table 4.nnn state, but not table 9.nnn state.

        Issue #25 in the EXT_framebuffer_object specification is relevant
        here.  Issue #25 (the issue could be more clear...) indicates
        that zero may be returned if a given buffer is not attached
        (the case where the framebuffer object is inconsistent).

        The GL_FRAMEBUFFER_UNSUPPORTED status can occur due to "an
        implementation-dependent set of restrictions".  Presumably these
        restrictions might not be evaluated until glBindFramebuffer
        time.  This blanket "didn't work" status means the appropriate
        per-framebuffer state may not be determined without binding to
        the framebuffer object.

        A future revision of this specification (such as its integration
        into an FBO-enabled core specification) may wish to reconsider
        this issue and add table 9.nnn state to the state queriable by
        glGetFramebufferParameteriv.

        If so, there should also be a query
        glGetFramebufferMultisamplefvEXT for NV_explicit_multisample
        for similar reasons. 

            void GetFramebufferMultisamplefvEXT(uint framebuffer,
                                                enum pname, uint index,
                                                float *val);

   (25) Should the selector-free versions of various OpenGL 3.0 and
        EXT_framebuffer_object framebuffer object commands not be allowed
        in display lists when the selector-based versions are specified
        to not be compiled into display lists?

        RESOLVED:  Yes, keep this same restriction.

        It is unfortunate that commands such as glGenerateMipmap
        are explicitly specified to not be compiled into display lists;
        this extension simply retains these same restrictions.

   (26) Direct state access commands and queries can implicit object
        initialization when provided unused object names.  If implicit
        object initialization is required but the command would
        subsequently generate an error, should the object be initialized
        and the name now be used?

        RESOLVED:  Yes, an object for an unused name can be initialized
        but if the command generates an error, the object should still
        be initialized and the name now used.

        Most OpenGL commands (excepting GL_OUT_OF_MEMORY errors) are
        ignored if an error occurs.

        Direct state access commands are an exception because they
        should be "morally equivalent" to doing a glBind* followed by
        the selector-based command.  For example:

            GLuint update2D = 27;
            glTextureImage2D(update2D, GL_TEXTURE_2D, ...);

        should be morally equivalent to:

            GLuint update2D = 27;
            GLint bound2D;
            glGetIntegerv(GL_TEXTURE_BINDING_2D, &bound2D);
            glBindTexture(GL_TEXTURE_2D, update2D);
            glTexImage2D(GL_TEXTURE_2D, ...);
            glBindTexture(GL_TEXTURE_2D, bound2D);

        If the ... arguments to glTexImage2D and glTextureImage2D
        resulted in an error (say a GL_INVALID_ENUM), in both cases we
        want texture object 27 to exist after the sequence.

        The rationale for this behavior is an application lacking
        EXT_direct_state_access should be able to generate equivalent
        command sequences and have "morally equivalent" error behavior.

        It is deemed undesirable for an non-EXT_direct_state_access path
        to behave differently (initializing unused objects on glBind*)
        despite an error in the subsequent state-setting command or
        state-querying query.

   (27) How many entry points are introduced?

        This extension adds just 3 tokens but specifies 214 functions
        (192 for version 1.0 plus 22 for OpenGL 3.0 support added by
        version 1.1).

        Technically 5 of these functions were previously introduced by
        EXT_draw_buffers2 and are now part of OpenGL 3.0.

        OpenGL 2.1 and 3.0 contains 583 and 666 functions respectively.
        So the OpenGL 2.1 subset of EXT_direct_state_access is +22%
        more functions beyond OpenGL 2.1's function set.

        By comparison, OpenGL 2.0 added 93 functions (primarily for GLSL
        support) to OpenGL 1.5's 484 functions, a +19% increase in the
        function set.  OpenGL 3.0 added 83 new functions.

        OpenGL's immediate mode API function count is considerably
        larger than the number of EXT_direct_state_access functions.
        There are 212 "vertex attribute" functions (counting all core
        OpenGL 2.1 glVertex*, glColor*, glSecondaryColor*, glNormal*,
        glTexCoord*, glMultiTexCoord*, glVertexAttrib*, glMaterial*,
        glRasterPos*, and glWindowPos* variants).

        So the core EXT_direct_state_access function count is 63% of
        the count of core OpenGL 2.1 "vertex attribute" functions.

        Another way to measure the footprint of EXT_direct_state_access
        is in terms of the optimized compiled user-space driver
        the size (text+data) of a modern Windows XP OpenGL driver
        supporting EXT_direct_state_access compared to the same
        driver without EXT_direct_state_access supported compiled in.
        The EXT_direct_state_access driver is +2.5% larger.

   (28) How should vertex array objects be supported?

        RESOLVED:  The EXT version of this specification didn't provide
        interactions with the glVertexArrayBindAPPLE selector introduced
        by the APPLE_vertex_buffer_object extension.  Now that this
        extension is incorporated into OpenGL 3.0, it makes sense for
        an ARB extension to incorporate selector-free support for vertex
        buffer objects.

        Selector-free versions of the vertex array specification commands
        are of the form (using glColorPointer as an example):

            void glVertexArrayColorOffsetEXT(uint vaobj, uint buffer,
                                             int size, enum type, sizei stride,
                                             intptr offset);

        There are two initial parameter for both the vertex array
        object selector (vaobj) and the latched buffer state (buffer).

        The vaobj parameter is needed for the commands to be
        selector-free.  The latched buffer is an explicit parameter to
        avoid having disturb the GL_ARRAY_BUFFER selector.

        (While using glPushClientAttribDefaultEXT/glPopClientAttrib
        works to avoid disturbing latched client vertex array buffer
        binding state--ignoring client attrib stack overflows--that
        approach doesn't work for vertex array objects because
        glPushClientAttribDefaultARB/glPopClientAttrib would default all
        the initial values of the currently bound vertex array object.)

        Also the last "const GLvoid * pointer" parameter is changed to
        an "intptr offset" parameter.  This change reflects the more
        encouraged and generally more efficient usage of pulling vertex
        arrays from vertex buffer objects.  This usage avoids having to
        always cast an offset to a pointer.

        Because the GLintptr type has the same sizeof as a pointer,
        applications seeking to pass pointers with a zero value for the
        buffer parameter can do so by casting their pointer to a GLintptr.
        Example:

            static GLfloat colors[3*20];
            glVertexArrayColorOffsetEXT(27, /*client-state*/0,
                                        3, GL_FLOAT, 12, (GLintptr)colors);

        Also added are selector-free vertex array object enable/disable
        commands and queries.  The queries return GLintptr values to
        make sure pointers as well as offsets can be returned.

   (29) How should vertex array object queries be supported?

        RESOLVED:  Provide both glGetVertexArray*Parameteriv and
        glGetVertexArray*Pointerv queries.

        Rather than providing both integer and pointer queries, it is
        tempting to provide just a query accepting a GLintptr pointer.
        But that's a likely pitfall for 64-bit coding.  Someone coding for
        32-bit could pass a GLint* without complaint from the compiler
        since both GLint* and GLintptr* are pointers to a 32-bit value,
        but in a 64-bit compilation environment, GLintptr* is a pointer
        to a 64-bit value.  While 64-bit compilers are likely to error
        (or at least warn) about this situation, a GLintptr* is likely
        to encourage 64-bit portability problems.  Having both a pointer
        and integer query avoids this problem.

   (30) What should happen when a negative offset is passed to the
        glVertexArray*OffsetEXT routines?

        RESOLVED:  When the buffer is non-zero, the offset really should
        be a positive value so generate an GL_INVALID_VALUE if a negative
        offset is passed to these routines when buffer is non-zero.
        When the buffer is non-negative, the GLintptr offset parameter
        will be treated as a pointer; in this case, there should be
        no check for negative values of the offset parameter since the
        negative parameter could, in fact, be a valid pointer.

        This raises the interesting point as to whether the several
        core OpenGL buffer API commands such as glBufferSubData,
        glMapBufferRange, and glFlushMappedBufferRange should actually
        have a type of GLsizeiptr for their offset parameter.  Doing so
        would simplify the language in section 2.9 (Buffer Object) by
        eliminating the need to document GL_INVALID_OFFSET errors for
        negative offset parameters.  Such a change could be made in a
        compatible way because GLintptr and GLsizeiptr are typedef'ed
        to the same underlying type (a signed int of the same size in
        bytes as a pointer).

   (31) Should the internalformat parameter of various DSA versions of
        gl*Tex*Image* routines be a GLint or GLenum?

        RESOLVED:  Match the type for internalformat of the pre-DSA
        version of the routine.

        This is a legacy of OpenGL 1.0 where the internalformat parameter
        to glTexImage1D and glTexImage2D was a GLint-typed value that
        could be 1, 2, 3, or 4 for the number of components.

        In OpenGL 1.1, internal texture formats were introduced to provide
        more specificity to the internal representation of texels within
        a texture.  This was part of introducing texture objects to OpenGL
        (a feature not originally in OpenGL 1.0).

        The intent of this decision is to make it easier for existing
        code converting use the selector-free DSA routines without
        signed/unsigned warnings because GLenum is unsigned while GLint
        is signed.

        This means the following commands take a GLint internalformat
        parameter:

            glTextureImage1DEXT
            glTextureImage2DEXT
            glTextureImage3DEXT
            glMultiTexImage1DEXT
            glMultiTexImage2DEXT
            glMultiTexImage3DEXT

        This means the following commands take a GLenum internalformat
        parameter:

            glCopyTextureImage1DEXT
            glCopyTextureImage2DEXT
            glCopyMultiTexImage1DEXT
            glCopyMultiTexImage2DEXT

            glCompressedTextureImage1DEXT
            glCompressedTextureImage2DEXT
            glCompressedTextureImage3DEXT
            glCompressedMultiTexImage1DEXT
            glCompressedMultiTexImage2DEXT
            glCompressedMultiTexImage3DEXT

            glTextureBufferEXT
            glMultiTexBufferEXT
            glNamedRenderbufferStorageEXT
            glNamedRenderbufferStorageMultisampleEXT
            glNamedRenderbufferStorageMultisampleCoverageEXT

        Warning: pre-July 2013 versions of glext.h have the DSA prototypes that
        should be using GLint internalformat using GLenum instead.  See:

            https://cvs.khronos.org/bugzilla/show_bug.cgi?id=10413

   (32) How can a particular vertex array object's texture coordinate
        set array be updated without depending on the active client
        texture selector?

        RESOLVED:  The glEnableVertexArrayEXT and glDisableVertexArrayEXT
        commands should be extended to accept GL_TEXTUREi tokens where
        GL_TEXTUREi indicates the specific vertex array for texture
        coordinate set i to enable or disable respectively.

        Due to a specification lapse, this behavior was not specified in
        the version 1.1 of this specification but was added for version
        1.2.

        The use of a GL_TEXTUREi token follows the precedent set for how
        GL_TEXTUREi is supported for the selector-free matrix routines.

        Implementations of EXT_direct_state_access prior to July 2013
        cannot be expected to implement this behavior and will generate
        a GL_INVALID_ENUM error instead.  This error can be used to
        distinguish version 1.2 and earlier versions of this extension.

        Calling glEnableVertexArrayEXT or glDisableVertexArrayEXT with
        GL_TEXTURE_COORD_ARRAY can be expected to update the texture
        coordinate array based on the current active client texture
        coordinate set of the indicated vertex array object, effectively
        depending on the current active texture selector but not the
        current bound vertex array object selector.

        Querying the enable of multitexture texture coordinate arrays
        uses glGetVertexArrayIntegeri_vEXT with GL_TEXTURE_COORD_ARRAY
        for the pname.  This behavior was not clearly specified before
        version 1.2.

Revision History

    Rev.    Date    Author    Changes
    ----  --------  --------  -----------------------------------------
     1    11/20/07  mjk       Initial version
     2    12/03/07  mjk       Feedback from JeffB
     3    01/02/08  mjk       Formatting
     4    01/02/08  mjk       NV_gpu_program4 additions
     5    01/02/08  mjk       EXT_gpu_program_parameters additions
     6    03/06/08  mjk       Switch from "MultiTex" to "Indexed"
                              texture API
     7    03/27/08  mjk       Feedback from TransGaming
     8    03/28/08  mjk       Program matrix query and
                              indexed query restructuring
     9    03/31/08  mjk       MultiTex API complete
     10   04/03/08  mjk       Fix CompressedTexture and CompressedMultiTex
                              lapses noticed by Ian
     11   04/14/08  mjk       Add target parameters to NamedProgram and
                              GetNamedProgram calls
     12   04/17/08  mjk       ARB_texture_rectangle interaction
     13   04/28/08  mjk       Add issue #19
     14   05/02/08  mjk       Add issue #20 about multi-thread
                              interactions as suggested by Yanjun Zhang
     15   05/06/08  mjk       Typos: glGetMultiTexCompressedTextureEXT
                              prototype and GLX protocol suffixing
     16   05/22/08  mjk       Add FBO support
     17   05/23/08  mjk       Fix Generate{Texture,MultiTex}MipmapEXT
     18   06/06/08  mjk       glCheckNamedFramebufferStatusEXT needs target
                              Issues #22 and #23
     19   06/10/08  mjk       Add FramebufferDrawBufferEXT,
                              FramebufferDrawBuffersEXT,
                              FramebufferReadBufferEXT
     20   07/01/08  mjk       Add NV_explicit_multisample interaction
     21   07/07/08  mjk       Typo fixes from Daniel Koch, error
                              semantics, new issues, limit
                              GetFramebufferParameterivEXT to 4.nnn state,
                              fix NamedProgramStringEXT discussion,
                              add EXT_texture_array and
                              NV_texture_cube_map_array interactions
     22   07/15/08  mjk       Just typos
     23   11/05/08  mjk       Destineer support
     24   11/05/08  mjk       Destineer support
     25   12/15/08  mjk       Version 1.1 adds OpenGL 3.0 support
     26   12/19/08  mjk       Fix VertexArrayVertexOffsetEXT duplicate
                              entry point; eliminated version missing stride
     27   12/22/08  mjk       NamedRenderbufferStorageEXT shouldn't have
                              target parameter
     28   12/23/08  mjk       Fixed various "index" functions for 3.0
     29   01/12/09  mjk       Add error for negative offsets for
                              glVertexArray*Offset commands when buffer
                              parameter is non-zero
     30   01/26/09  mjk       Correct glPopClientAttrib usage
     31   02/17/09  mjk       Add glVertexArrayMultiTexCoordOffsetEXT
                              New names: GetVertexArrayIntegeri_vEXT,
                              GetVertexArrayIntegervEXT,
                              GetVertexArrayPointeri_vEXT
     32   03/13/09  groth     Add EXT_copy_buffer interaction
     33   06/10/09  mjk       add VertexArrayMultiTexCoordOffsetEXT to
                              list of errors for exceeding the maximum
                              texture image units
     34   09/07/10  mjk       some Get*Indexedv instanced needed EXT
                              suffixes; issue 27 update
     35   06/18/13  mjk       add issue 31; glext.h had GLenum internalformat
                              when spec said GLint for gl*Tex*Image*EXT commands
     36   06/24/13  mjk       fix glEnableVertexArrayEXT and
                              glDisableVertexArrayEXT so they accept the
                              GL_TEXTUREi tokens to be free of active
                              client texture selector (issue 32)
     37   07/29/13  mjk       document NVIDIA driver bugs
     38   10/22/13  mjk       add Matrix*Transpose*EXT routines missing
                              from section 2.12.2 list
     39   02/24/15  mjk       add & operator to glMultiTexGenivEXT in NV Impl.
