Added __glExtensionBiIsEnabled and __GLXcontext::gl_extension_bits.  This
enables libGL to query which extension are exported to applications.

Refactored array-query functionality (from glGet*v) in src/glx/x11/single2.c.

Massive re-write of indirect vertex array support.  The most noticable
effect is that glDrawElements now generates DrawArrays protocol.  The
side-effects (and the main reasons for the re-work) are that it is much
easier to add support for new arrays (e.g., GL_VERTEX_ATTRIB_ARRAY,
GL_WEIGHT_ARRAY_ARB, etc.) and it is much easier to add support for the new
DrawArrays protocol (required to support ARB_vertex_buffer_object).

These changes were primarilly tested with progs/demos/isosurf.
diff --git a/src/glx/x11/clientattrib.c b/src/glx/x11/clientattrib.c
index 298978f..9cfb3c9 100644
--- a/src/glx/x11/clientattrib.c
+++ b/src/glx/x11/clientattrib.c
@@ -36,77 +36,34 @@
 
 #include <assert.h>
 #include "glxclient.h"
+#include "indirect_vertex_array.h"
 
 /*****************************************************************************/
 
-void __indirect_glEnableClientState(GLenum array)
+static void
+do_enable_disable(GLenum array, GLboolean val )
 {
     __GLXcontext *gc = __glXGetCurrentContext();
     __GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
+    unsigned index = 0;
 
-    switch (array) {
-	case GL_COLOR_ARRAY:
-	    ENABLE_ARRAY(state, color);
-	    break;
-	case GL_EDGE_FLAG_ARRAY:
-	    ENABLE_ARRAY(state, edgeFlag);
-	    break;
-	case GL_INDEX_ARRAY:
-	    ENABLE_ARRAY(state, index);
-	    break;
-	case GL_NORMAL_ARRAY:
-	    ENABLE_ARRAY(state, normal);
-	    break;
-	case GL_TEXTURE_COORD_ARRAY:
-	    ENABLE_TEXARRAY(state, state->vertArray.activeTexture);
-	    break;
-	case GL_VERTEX_ARRAY:
-	    ENABLE_ARRAY(state, vertex);
-	    break;
-	case GL_SECONDARY_COLOR_ARRAY:
-	    ENABLE_ARRAY(state, secondaryColor);
-	    break;
-	case GL_FOG_COORD_ARRAY:
-	    ENABLE_ARRAY(state, fogCoord);
-	    break;
-	default:
-	    __glXSetError(gc, GL_INVALID_ENUM);
+    if ( array == GL_TEXTURE_COORD_ARRAY ) {
+	index = __glXGetActiveTextureUnit( state );
     }
+
+    if ( ! __glXSetArrayEnable( state, array, index, val ) ) {
+	__glXSetError(gc, GL_INVALID_ENUM);
+    }
+}
+
+void __indirect_glEnableClientState(GLenum array)
+{
+    do_enable_disable( array, GL_TRUE );
 }
 
 void __indirect_glDisableClientState(GLenum array)
 {
-    __GLXcontext *gc = __glXGetCurrentContext();
-    __GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
-
-    switch (array) {
-	case GL_COLOR_ARRAY:
-	    DISABLE_ARRAY(state, color);
-	    break;
-	case GL_EDGE_FLAG_ARRAY:
-	    DISABLE_ARRAY(state, edgeFlag);
-	    break;
-	case GL_INDEX_ARRAY:
-	    DISABLE_ARRAY(state, index);
-	    break;
-	case GL_NORMAL_ARRAY:
-	    DISABLE_ARRAY(state, normal);
-	    break;
-	case GL_TEXTURE_COORD_ARRAY:
-	    DISABLE_TEXARRAY(state, state->vertArray.activeTexture);
-	    break;
-	case GL_VERTEX_ARRAY:
-	    DISABLE_ARRAY(state, vertex);
-	    break;
-	case GL_SECONDARY_COLOR_ARRAY:
-	    DISABLE_ARRAY(state, secondaryColor);
-	    break;
-	case GL_FOG_COORD_ARRAY:
-	    DISABLE_ARRAY(state, fogCoord);
-	    break;
-	default:
-	    __glXSetError(gc, GL_INVALID_ENUM);
-    }
+    do_enable_disable( array, GL_FALSE );
 }
 
 /************************************************************************/
@@ -129,7 +86,7 @@
 	    sp->storeUnpack = state->storeUnpack;
 	}
 	if (mask & GL_CLIENT_VERTEX_ARRAY_BIT) {
-	    sp->vertArray = state->vertArray;
+	    __glXPushArrayState( state );
 	}
     } else {
 	__glXSetError(gc, GL_STACK_OVERFLOW);
@@ -156,7 +113,7 @@
 	    state->storeUnpack = sp->storeUnpack;
 	}
 	if (mask & GL_CLIENT_VERTEX_ARRAY_BIT) {
-	    state->vertArray = sp->vertArray;
+	    __glXPopArrayState( state );
 	}
 
 	sp->mask = 0;
@@ -181,5 +138,3 @@
 	}
     }
 }
-
-
diff --git a/src/glx/x11/glxclient.h b/src/glx/x11/glxclient.h
index d0cc12e..4356ee8 100644
--- a/src/glx/x11/glxclient.h
+++ b/src/glx/x11/glxclient.h
@@ -59,6 +59,7 @@
 #include "GL/glxproto.h"
 #include "GL/internal/glcore.h"
 #include "glapitable.h"
+#include "glxextensions.h"
 #ifdef XTHREADS
 #include "Xthreads.h"
 #endif
@@ -220,110 +221,29 @@
 	__GLXvertArrayStateDEPRECATED vertArray;
 } __GLXattributeDEPRECATED;
 
-typedef struct __GLXvertexArrayPointerStateRec {
-    void (*proc)(const void *);
-    void (*mtex_proc)(GLenum, const void *);
-    const GLubyte *ptr;
-    GLsizei skip;
-    GLint size;
-    GLenum type;
-    GLsizei stride;
-} __GLXvertexArrayPointerState;
-
-/**
- * Define which entries of \c __GLXvertArrayState::arrays match which
- * vertex arrays in the client-state vector.  These are only the one-of
- * arrays.  See the \c __GLXvertArrayState::arrays documentation for more
- * details.
- * 
- * \sa __GLXvertArrayState
- */
-enum {
-    edgeFlag_ARRAY,       /**< \c GL_EDGE_FLAG_ARRAY */
-    index_ARRAY,          /**< \c GL_INDEX_ARRAY */
-    fogCoord_ARRAY,       /**< \c GL_FOG_COORD_ARRAY */
-    secondaryColor_ARRAY, /**< \c GL_SECONDARY_COLOR_ARRAY */
-    color_ARRAY,          /**< \c GL_COLOR_ARRAY */
-    normal_ARRAY,         /**< \c GL_NORMAL_ARRAY */
-       
-    /**
-     * \c GL_VERTEX_ARRAY \b must be last!  All of the code for emitting arrays
-     * and array elements is written based on the assumption that the vertex
-     * array is last.
-     */
-    vertex_ARRAY,
-
-    __GLX_MAX_ARRAYS      /**< Place holder entry. */
-};
-
-#define ENABLE_ARRAY(state,a) \
-    do { (state)->vertArray.enables |=  (1U << (a ## _ARRAY)); } while( 0 )
-#define DISABLE_ARRAY(state,a) \
-    do { (state)->vertArray.enables &= ~(1U << (a ## _ARRAY)); } while( 0 )
-#define IS_ARRAY_ENABLED_BY_INDEX(state, i) \
-    (((state)->vertArray.enables & (1U << (i))) != 0)
-#define IS_ARRAY_ENABLED(state, a) \
-    IS_ARRAY_ENABLED_BY_INDEX(state, a ## _ARRAY)
-
-#define ENABLE_TEXARRAY(state,a) \
-    do { (state)->vertArray.texture_enables |=  (1U << a); } while( 0 )
-#define DISABLE_TEXARRAY(state,a) \
-    do { (state)->vertArray.texture_enables &= ~(1U << a); } while( 0 )
-#define IS_TEXARRAY_ENABLED(state, a) \
-    (((state)->vertArray.texture_enables & (1U << a)) != 0)
-
-/**
- * Client-side vertex array state.
- */
-typedef struct __GLXvertArrayStateRec {
-    /**
-     * Which client-side arrays are enabled?  These are the flag bits for
-     * all of the non-texture coordinate arrays.
-     */
-    GLuint enables;
-
-    /**
-     * Which of the texture coordinate arrays are enabled?
-     */
-    GLuint texture_enables;
-
-    /**
-     * State for "one-of" arrays.  These are the arrays, such as
-     * GL_COLOR_ARRAY or GL_FOG_COORD_ARRAY for which there is only one
-     * array.  There are also "many-of" arrays, such as
-     * GL_TEXTURE_COORD_ARRAY.
-     */
-    __GLXvertexArrayPointerState arrays[__GLX_MAX_ARRAYS];
-
-    __GLXvertexArrayPointerState texCoord[__GLX_MAX_TEXTURE_UNITS];
-
-    GLint maxElementsVertices;
-    GLint maxElementsIndices;
-    GLint activeTexture;
-} __GLXvertArrayState;
 
 typedef struct __GLXattributeRec {
-	GLuint mask;
+    GLuint mask;
 
-	/*
-	** Pixel storage state.  Most of the pixel store mode state is kept
-	** here and used by the client code to manage the packing and
-	** unpacking of data sent to/received from the server.
-	*/
-	__GLXpixelStoreMode storePack, storeUnpack;
+    /**
+     * Pixel storage state.  Most of the pixel store mode state is kept
+     * here and used by the client code to manage the packing and
+     * unpacking of data sent to/received from the server.
+     */
+    __GLXpixelStoreMode storePack, storeUnpack;
 
-	/*
-	** Vertex Array storage state.  The vertex array component
-	** state is stored here and is used to manage the packing of
-	** DrawArrays data sent to the server.
-	*/
-	__GLXvertArrayState vertArray;
-
-	/**
-	 * Is EXT_vertex_array / GL 1.1 DrawArrays protocol specifically
-	 * disabled?
-	 */
-	GLboolean NoDrawArraysProtocol;
+    /**
+     * Is EXT_vertex_array / GL 1.1 DrawArrays protocol specifically
+     * disabled?
+     */
+    GLboolean NoDrawArraysProtocol;
+    
+    /**
+     * Vertex Array storage state.  The vertex array component
+     * state is stored here and is used to manage the packing of
+     * DrawArrays data sent to the server.
+     */
+    struct array_state_vector * array_state;
 } __GLXattribute;
 
 typedef struct __GLXattributeMachineRec {
@@ -529,7 +449,7 @@
     * drivers should NEVER use this data or even care that it exists.
     */
    void * client_state_private;
-   
+
    /**
     * Stored value for \c glXQueryContext attribute \c GLX_RENDER_TYPE.
     */
@@ -546,6 +466,8 @@
    int server_major;        /**< Major version number. */
    int server_minor;        /**< Minor version number. */
     /*@}*/
+
+    char gl_extension_bits[ __GL_EXT_BYTES ];
 };
 
 #define __glXSetError(gc,code) \
diff --git a/src/glx/x11/glxcmds.c b/src/glx/x11/glxcmds.c
index c76502c..8d6dca2 100644
--- a/src/glx/x11/glxcmds.c
+++ b/src/glx/x11/glxcmds.c
@@ -375,8 +375,6 @@
     state->storePack.alignment = 4;
     state->storeUnpack.alignment = 4;
 
-    __glXInitVertexArrayState(gc);
-
     gc->attributes.stackPointer = &gc->attributes.stack[0];
 
     /*
diff --git a/src/glx/x11/glxextensions.c b/src/glx/x11/glxextensions.c
index 9623cdf..f4e07ef 100644
--- a/src/glx/x11/glxextensions.c
+++ b/src/glx/x11/glxextensions.c
@@ -237,8 +237,6 @@
 };
 
 
-#define __GL_EXT_BYTES   ((__NUM_GL_EXTS + 7) / 8)
-
 /* global bit-fields of available extensions and their characteristics */
 static unsigned char client_glx_support[8];
 static unsigned char client_glx_only[8];
@@ -494,6 +492,24 @@
 
 
 /**
+ * Check if a certain extension is enabled in a given context.
+ *
+ */
+GLboolean
+__glExtensionBitIsEnabled( const __GLXcontext * gc, unsigned bit )
+{
+   GLboolean enabled = GL_FALSE;
+
+   if ( gc != NULL ) {
+      enabled = EXT_ENABLED( bit, gc->gl_extension_bits );
+   }
+
+   return enabled;
+}
+
+
+
+/**
  * Convert a bit-field to a string of supported extensions.
  */
 static char *
@@ -680,6 +696,7 @@
 
    gc->extensions = (unsigned char *) 
      __glXGetStringFromTable( known_gl_extensions, usable );
+   (void) memcpy( gc->gl_extension_bits, usable, sizeof( usable ) );
 }
 
 
diff --git a/src/glx/x11/glxextensions.h b/src/glx/x11/glxextensions.h
index e7d0248..c64561b 100644
--- a/src/glx/x11/glxextensions.h
+++ b/src/glx/x11/glxextensions.h
@@ -216,16 +216,25 @@
    GL_SUN_multi_draw_arrays_bit = GL_EXT_multi_draw_arrays_bit
 };
 
-extern GLboolean __glXExtensionBitIsEnabled( __GLXscreenConfigs *psc, unsigned bit );
+#define __GL_EXT_BYTES   ((__NUM_GL_EXTS + 7) / 8)
+
+struct __GLXscreenConfigsRec;
+struct __GLXcontextRec;
+
+extern GLboolean __glXExtensionBitIsEnabled( struct __GLXscreenConfigsRec *psc, unsigned bit );
 extern const char * __glXGetClientExtensions( void );
-extern void __glXCalculateUsableExtensions( __GLXscreenConfigs *psc,
+extern void __glXCalculateUsableExtensions( struct __GLXscreenConfigsRec *psc,
     GLboolean display_is_direct_capable, int server_minor_version );
-extern void __glXScrEnableExtension( __GLXscreenConfigs *psc, const char * name );
-extern void __glXCalculateUsableGLExtensions( __GLXcontext * gc,
+extern void __glXScrEnableExtension( struct __GLXscreenConfigsRec *psc, const char * name );
+extern void __glXCalculateUsableGLExtensions( struct __GLXcontextRec * gc,
     const char * server_string, int major_version, int minor_version );
 extern void __glXGetGLVersion( int * major_version, int * minor_version );
 extern char * __glXGetClientGLExtensionString( void );
 
+extern GLboolean __glExtensionBitIsEnabled( const struct __GLXcontextRec * gc, 
+    unsigned bit );
+
+
 /* Source-level backwards compatibility with old drivers. They won't
  * find the respective functions, though. 
  */
diff --git a/src/glx/x11/indirect_vertex_array.c b/src/glx/x11/indirect_vertex_array.c
new file mode 100644
index 0000000..8bc7e44
--- /dev/null
+++ b/src/glx/x11/indirect_vertex_array.c
@@ -0,0 +1,1878 @@
+/*
+ * (C) Copyright IBM Corporation 2004, 2005
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
+ * IBM,
+ * AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <inttypes.h>
+#include <assert.h>
+#include "glxclient.h"
+#include "packrender.h"
+#include "indirect.h"
+#include <string.h>
+
+#include <GL/glxproto.h>
+#include "glxextensions.h"
+#include "indirect_vertex_array.h"
+
+/**
+ * \file indirect_vertex_array.c
+ * Implement GLX protocol for vertex arrays and vertex buffer objects.
+ * 
+ * The most important function in this fill is \c fill_array_info_cache.
+ * The \c array_state_vector contains a cache of the ARRAY_INFO data sent
+ * in the DrawArrays protocol.  Certain operations, such as enabling or
+ * disabling an array, can invalidate this cache.  \c fill_array_info_cache
+ * fills-in this data.  Additionally, it examines the enabled state and
+ * other factors to determine what "version" of DrawArrays protocoal can be
+ * used.
+ * 
+ * Current, only two versions of DrawArrays protocol are implemented.  The
+ * first version is the "none" protocol.  This is the fallback when the
+ * server does not support GL 1.1 / EXT_vertex_arrays.  It is implemented
+ * by sending batches of immediate mode commands that are equivalent to the
+ * DrawArrays protocol.
+ *
+ * The other protocol that is currently implemented is the "old" protocol.
+ * This is the GL 1.1 DrawArrays protocol.  The only difference between GL
+ * 1.1 and EXT_vertex_arrays is the opcode used for the DrawArrays command.
+ * This protocol is called "old" because the ARB is in the process of
+ * defining a new protocol, which will probably be called wither "new" or
+ * "vbo", to support multiple texture coordinate arrays, generic attributes,
+ * and vertex buffer objects.
+ *
+ * \author Ian Romanick <idr@us.ibm.com>
+ */
+
+
+/**
+ * State descriptor for a single array of vertex data.
+ */
+struct array_state {
+    /**
+     * Pointer to the application supplied data.
+     */
+    const void * data;
+    
+    /**
+     * Enum representing the type of the application supplied data.
+     */
+    GLenum data_type;
+
+    /**
+     * Stride value supplied by the application.  This value is not used
+     * internally.  It is only kept so that it can be queried by the
+     * application using glGet*v.
+     */
+    GLsizei user_stride;
+
+    /**
+     * Calculated size, in bytes, of a single element in the array.  This
+     * is calculated based on \c count and the size of the data type
+     * represented by \c data_type.
+     */
+    GLsizei element_size;
+
+    /**
+     * Actual byte-stride from one element to the next.  This value will
+     * be equal to either \c user_stride or \c element_stride.
+     */
+    GLsizei true_stride;
+
+    /**
+     * Number of data values in each element.
+     */
+    GLint count;
+
+    /**
+     * Pre-calculated GLX protocol command header.
+     */
+    uint32_t header[2];
+    
+    /**
+     * Size of the header data.  For simple data, like glColorPointerfv,
+     * this is 4.  For complex data that requires either a count (e.g.,
+     * glWeightfvARB), an index (e.g., glVertexAttrib1fvARB), or a
+     * selector enum (e.g., glMultiTexCoord2fv) this is 8.
+     */
+    unsigned header_size;
+    
+    /**
+     * Set to \c GL_TRUE if this array is enabled.  Otherwise, it is set
+     * to \c GL_FALSE.
+     */
+    GLboolean  enabled;
+
+    /**
+     * For multi-arrayed data (e.g., texture coordinates, generic vertex
+     * program attributes, etc.), this specifies which array this is.
+     */
+    unsigned index;
+    
+    /**
+     * Per-array-type key.  For most arrays, this will be the GL enum for
+     * that array (e.g., GL_VERTEX_ARRAY for vertex data, GL_NORMAL_ARRAY
+     * for normal data, GL_TEXTURE_COORD_ARRAY for texture coordinate data,
+     * etc.).
+     */
+    GLenum key;
+
+    /**
+     * If this array can be used with the "classic" \c glDrawArrays protocol,
+     * this is set to \c GL_TRUE.  Otherwise, it is set to \c GL_FALSE.
+     */
+    GLboolean old_DrawArrays_possible;
+};
+
+
+/**
+ * Array state that is pushed / poped by \c glPushClientAttrib and
+ * \c glPopClientAttrib.
+ */
+struct array_stack_state {
+    /**
+     * Pointer to the application supplied data.
+     */
+    const void * data;
+    
+    /**
+     * Enum representing the type of the application supplied data.
+     */
+    GLenum data_type;
+
+    /**
+     * Stride value supplied by the application.  This value is not used
+     * internally.  It is only kept so that it can be queried by the
+     * application using glGet*v.
+     */
+    GLsizei user_stride;
+
+    /**
+     * Number of data values in each element.
+     */
+    GLint count;
+
+    /**
+     * Per-array-type key.  For most arrays, this will be the GL enum for
+     * that array (e.g., GL_VERTEX_ARRAY for vertex data, GL_NORMAL_ARRAY
+     * for normal data, GL_TEXTURE_COORD_ARRAY for texture coordinate data,
+     * etc.).
+     */
+    GLenum key;
+
+    /**
+     * For multi-arrayed data (e.g., texture coordinates, generic vertex
+     * program attributes, etc.), this specifies which array this is.
+     */
+    unsigned index;
+
+    /**
+     * Set to \c GL_TRUE if this array is enabled.  Otherwise, it is set
+     * to \c GL_FALSE.
+     */
+    GLboolean  enabled;
+};
+
+
+/**
+ * Collection of all the vertex array state.
+ */
+struct array_state_vector {
+    /**
+     * Number of arrays tracked by \c ::arrays.
+     */
+    size_t num_arrays;
+
+    /**
+     * Array of vertex array state.  This array contains all of the valid
+     * vertex arrays.  If a vertex array isn't in this array, then it isn't
+     * valid.  For example, if an implementation does not support
+     * EXT_fog_coord, there won't be a GL_FOG_COORD_ARRAY entry in this
+     * array.
+     */
+    struct array_state * arrays;
+
+    /**
+     * Number of currently enabled arrays.  The value of this field is
+     * only valid if \c array_info_cache_valid is true.
+     */
+    size_t enabled_array_count;
+
+    /**
+     * \name ARRAY_INFO cache.
+     * 
+     * These fields track the state of the ARRAY_INFO cache.  The
+     * \c array_info_cache_size is the size of the actual data stored in
+     * \c array_info_cache.  \c array_info_cache_buffer_size is the size of
+     * the buffer.  This will always be greater than or equal to
+     * \c array_info_cache_size.
+     *
+     * \c large_header doesn't completely belong in this group.  This is a
+     * pointer to a buffer to hold the header information for DrawArrays in
+     * a RenderLarge command.  This buffer is immediately before
+     * \c array_info_cache.  The idea is that the header data will be written
+     * to \c large_header and a single call to \c __glXSendLargeChunk can be
+     * made to send the header and the ARRAY_INFO data.
+     * 
+     * \note
+     * \c array_info_cache_size and \c array_info_cache_buffer_size do
+     * NOT include the size of \c large_header.
+     */
+    /*@{*/
+    size_t array_info_cache_size;
+    size_t array_info_cache_buffer_size;
+    void * array_info_cache;
+    GLubyte * large_header;
+    /*@}*/
+
+
+    /**
+     * Is the cache of ARRAY_INFO data valid?  The cache can become invalid
+     * when one of several state changes occur.  Among these chages are
+     * modifying the array settings for an enabled array and enabling /
+     * disabling an array.
+     */
+    GLboolean array_info_cache_valid;
+
+    /**
+     * Is it possible to use the GL 1.1 / EXT_vertex_arrays protocol?  Use
+     * of this protocol is disabled with really old servers (i.e., servers
+     * that don't support GL 1.1 or EXT_vertex_arrays) or when an environment
+     * variable is set.
+     * 
+     * \todo
+     * GL 1.1 and EXT_vertex_arrays use identical protocol, but have different
+     * opcodes for \c glDrawArrays.  For servers that advertise one or the
+     * other, there should be a way to select which opcode to use.
+     */
+    GLboolean old_DrawArrays_possible;
+
+    /**
+     * Is it possible to use the new GL X.X / ARB_vertex_buffer_object
+     * protocol?
+     * 
+     * \todo
+     * This protocol has not yet been defined by the ARB, but is currently a
+     * work in progress.  This field is a place-holder.
+     */
+    GLboolean new_DrawArrays_possible;
+
+    /**
+     * Active texture unit set by \c glClientActiveTexture.
+     * 
+     * \sa __glXGetActiveTextureUnit
+     */
+    unsigned active_texture_unit;
+    
+    /**
+     * Number of supported texture units.  Even if ARB_multitexture /
+     * GL 1.3 are not supported, this will be at least 1.  When multitexture
+     * is supported, this will be the value queried by calling
+     * \c glGetIntegerv with \c GL_MAX_TEXTURE_UNITS.
+     * 
+     * \todo
+     * Investigate if this should be the value of \c GL_MAX_TEXTURE_COORDS
+     * instead (if GL 2.0 / ARB_fragment_shader / ARB_fragment_program /
+     * NV_fragment_program are supported).
+     */
+    unsigned num_texture_units;
+
+    /**
+     * \n Methods for implementing various GL functions.
+     * 
+     * These method pointers are only valid \c array_info_cache_valid is set.
+     * When each function starts, it much check \c array_info_cache_valid.
+     * If it is not set, it must call \c fill_array_info_cache and call
+     * the new method.
+     * 
+     * \sa fill_array_info_cache
+     * 
+     * \todo
+     * Write code to plug these functions directly into the dispatch table.
+     */
+    /*@{*/
+    void (*DrawArrays)( GLenum, GLint, GLsizei );
+    void (*DrawElements)( GLenum mode, GLsizei count, GLenum type,
+			  const GLvoid *indices );
+    /*@}*/
+
+    struct array_stack_state * stack;
+    unsigned active_texture_unit_stack[ __GL_CLIENT_ATTRIB_STACK_DEPTH ];
+    unsigned stack_index;
+};
+
+
+static void emit_DrawArrays_none( GLenum mode, GLint first, GLsizei count );
+static void emit_DrawArrays_old ( GLenum mode, GLint first, GLsizei count );
+
+static void emit_DrawElements_none( GLenum mode, GLsizei count, GLenum type,
+    const GLvoid *indices );
+static void emit_DrawElements_old ( GLenum mode, GLsizei count, GLenum type,
+    const GLvoid *indices );
+
+
+static GLubyte * emit_element_none( GLubyte * dst,
+    const struct array_state_vector * arrays, unsigned index );
+static GLubyte * emit_element_old( GLubyte * dst,
+    const struct array_state_vector * arrays, unsigned index );
+static struct array_state * get_array_entry(
+    const struct array_state_vector * arrays, GLenum key, unsigned index );
+static void fill_array_info_cache( struct array_state_vector * arrays );
+static GLboolean glx_validate_array_args(__GLXcontext *gc, GLenum mode,
+    GLsizei count);
+
+
+/**
+ * Table of sizes, in bytes, of a GL types.  All of the type enums are be in 
+ * the range 0x1400 - 0x140F.  That includes types added by extensions (i.e.,
+ * \c GL_HALF_FLOAT_NV).  This elements of this table correspond to the
+ * type enums masked with 0x0f.
+ * 
+ * \notes
+ * \c GL_HALF_FLOAT_NV is not included.  Neither are \c GL_2_BYTES,
+ * \c GL_3_BYTES, or \c GL_4_BYTES.
+ */
+const GLuint __glXTypeSize_table[16] = {
+    1, 1, 2, 2, 4, 4, 4, 0, 0, 0, 8, 0, 0, 0, 0, 0
+};
+
+
+
+/**
+ * Initialize vertex array state of a GLX context.
+ * 
+ * \param gc  GLX context whose vertex array state is to be initialized.
+ * 
+ * \warning
+ * This function may only be called after __GLXcontext::gl_extension_bits,
+ * __GLXcontext::server_minor, and __GLXcontext::server_major have been
+ * initialized.  These values are used to determine what vertex arrays are
+ * supported.
+ * 
+ * \bug
+ * Return values from malloc are not properly tested.
+ */
+void
+__glXInitVertexArrayState( __GLXcontext * gc )
+{
+    __GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
+    struct array_state_vector * arrays;
+
+    unsigned array_count;
+    unsigned texture_units = 1;
+    unsigned i;
+
+    GLboolean got_fog = GL_FALSE;
+    GLboolean got_secondary_color = GL_FALSE;
+
+
+    arrays = malloc( sizeof( struct array_state_vector ) );
+    state->array_state = arrays;
+    arrays->enabled_array_count = 0;
+    arrays->array_info_cache = NULL;
+    arrays->array_info_cache_size = 0;
+    arrays->array_info_cache_buffer_size = 0;
+    arrays->array_info_cache_valid= GL_FALSE;
+
+    arrays->old_DrawArrays_possible = !state->NoDrawArraysProtocol;
+    arrays->new_DrawArrays_possible = GL_FALSE;
+    arrays->DrawArrays = NULL;
+
+    arrays->active_texture_unit = 0;
+
+
+    /* Determine how many arrays are actually needed.  Only arrays that
+     * are supported by the server are create.  For example, if the server
+     * supports only 2 texture units, then only 2 texture coordinate arrays
+     * are created.
+     * 
+     * At the very least, GL_VERTEX_ARRAY, GL_NORMAL_ARRAY,
+     * GL_COLOR_ARRAY, GL_INDEX_ARRAY, GL_TEXTURE_COORD_ARRAY, and
+     * GL_EDGE_FLAG_ARRAY are supported.
+     */
+    
+    array_count = 5;
+    
+    if ( __glExtensionBitIsEnabled( gc, GL_EXT_fog_coord_bit )
+	 || (gc->server_major > 1) || (gc->server_minor >= 4) ) {
+	got_fog = GL_TRUE;
+	array_count++;
+    }
+
+    if ( __glExtensionBitIsEnabled( gc, GL_EXT_secondary_color_bit )
+	 || (gc->server_major > 1) || (gc->server_minor >= 4) ) {
+	got_secondary_color = GL_TRUE;
+	array_count++;
+    }
+
+    if ( __glExtensionBitIsEnabled( gc, GL_ARB_multitexture_bit )
+	 || (gc->server_major > 1) || (gc->server_minor >= 3) ) {
+	glGetIntegerv( GL_MAX_TEXTURE_UNITS, & texture_units );
+    }
+    else {
+	texture_units = 1;
+    }
+
+    arrays->num_texture_units = texture_units;
+    array_count += texture_units;
+    arrays->num_arrays = array_count;
+    arrays->arrays = malloc( sizeof( struct array_state ) * array_count );
+    
+    (void) memset( arrays->arrays, 0,
+		   sizeof( struct array_state ) * array_count );
+
+
+    arrays->arrays[0].data_type = GL_FLOAT;
+    arrays->arrays[0].count = 3;
+    arrays->arrays[0].key = GL_NORMAL_ARRAY;
+    arrays->arrays[0].old_DrawArrays_possible = GL_TRUE;
+
+    arrays->arrays[1].data_type = GL_FLOAT;
+    arrays->arrays[1].count = 4;
+    arrays->arrays[1].key = GL_COLOR_ARRAY;
+    arrays->arrays[1].old_DrawArrays_possible = GL_TRUE;
+
+    arrays->arrays[2].data_type = GL_FLOAT;
+    arrays->arrays[2].count = 1;
+    arrays->arrays[2].key = GL_INDEX_ARRAY;
+    arrays->arrays[2].old_DrawArrays_possible = GL_TRUE;
+
+    arrays->arrays[3].data_type = GL_UNSIGNED_BYTE;
+    arrays->arrays[3].count = 1;
+    arrays->arrays[3].key = GL_EDGE_FLAG_ARRAY;
+    arrays->arrays[3].old_DrawArrays_possible = GL_TRUE;
+
+    for ( i = 0 ; i < texture_units ; i++ ) {
+	arrays->arrays[4 + i].data_type = GL_FLOAT;
+	arrays->arrays[4 + i].count = 4;
+	arrays->arrays[4 + i].key = GL_TEXTURE_COORD_ARRAY;
+	
+	arrays->arrays[4 + i].old_DrawArrays_possible = (i == 0);
+	arrays->arrays[4 + i].index = i;
+
+	arrays->arrays[4 + i].header[1] = i + GL_TEXTURE0;
+    }
+    
+    i = 4 + texture_units;
+
+    if ( got_fog ) {
+	arrays->arrays[i].data_type = GL_FLOAT;
+	arrays->arrays[i].count = 1;
+	arrays->arrays[i].key = GL_FOG_COORDINATE_ARRAY;
+	arrays->arrays[i].old_DrawArrays_possible = GL_TRUE;
+	i++;
+    }
+
+    if ( got_secondary_color ) {
+	arrays->arrays[i].data_type = GL_FLOAT;
+	arrays->arrays[i].count = 3;
+	arrays->arrays[i].key = GL_SECONDARY_COLOR_ARRAY;
+	arrays->arrays[i].old_DrawArrays_possible = GL_TRUE;
+	i++;
+    }
+
+
+    /* Vertex array *must* be last becuase of the way that
+     * emit_DrawArrays_none works.
+     */
+
+    arrays->arrays[i].data_type = GL_FLOAT;
+    arrays->arrays[i].count = 4;
+    arrays->arrays[i].key = GL_VERTEX_ARRAY;
+    arrays->arrays[i].old_DrawArrays_possible = GL_TRUE;
+
+
+    arrays->stack_index = 0;
+    arrays->stack = malloc( sizeof( struct array_stack_state )
+			    * arrays->num_arrays );
+}
+
+
+/**
+ * Calculate the size of a single vertex for the "none" protocol.  This is
+ * essentially the size of all the immediate-mode commands required to
+ * implement the enabled vertex arrays.
+ */
+static size_t
+calculate_single_vertex_size_none( const struct array_state_vector * arrays )
+{
+    size_t single_vertex_size = 0;
+    unsigned   i;
+
+
+    for ( i = 0 ; i < arrays->num_arrays ; i++ ) {
+    	if ( arrays->arrays[i].enabled ) {
+	    single_vertex_size += __GLX_PAD(arrays->arrays[i].element_size)
+	      + arrays->arrays[i].header_size;
+	}
+    }
+    
+    return single_vertex_size;
+}
+
+
+/**
+ * Emit a single element using non-DrawArrays protocol.
+ */
+GLubyte *
+emit_element_none( GLubyte * dst,
+		   const struct array_state_vector * arrays,
+		   unsigned index )
+{
+    unsigned i;
+
+
+    for ( i = 0 ; i < arrays->num_arrays ; i++ ) {
+	if ( arrays->arrays[i].enabled ) {
+	    const size_t offset = index * arrays->arrays[i].true_stride;
+
+	    (void) memcpy( dst, arrays->arrays[i].header, 
+			   arrays->arrays[i].header_size );
+
+	    dst += arrays->arrays[i].header_size;
+
+	    (void) memcpy( dst, ((GLubyte *) arrays->arrays[i].data) + offset,
+			   arrays->arrays[i].element_size );
+
+	    dst += __GLX_PAD( arrays->arrays[i].element_size );
+	}
+    }
+
+    return dst;
+}
+
+
+/**
+ * Emit a single element using "old" DrawArrays protocol from
+ * EXT_vertex_arrays / OpenGL 1.1.
+ */
+GLubyte *
+emit_element_old( GLubyte * dst,
+		  const struct array_state_vector * arrays,
+		  unsigned index )
+{
+    unsigned i;
+
+
+    for ( i = 0 ; i < arrays->num_arrays ; i++ ) {
+	if ( arrays->arrays[i].enabled ) {
+	    const size_t offset = index * arrays->arrays[i].true_stride;
+
+	    (void) memcpy( dst, ((GLubyte *) arrays->arrays[i].data) + offset,
+			   arrays->arrays[i].element_size );
+
+	    dst += __GLX_PAD( arrays->arrays[i].element_size );
+	}
+    }
+
+    return dst;
+}
+
+
+struct array_state *
+get_array_entry( const struct array_state_vector * arrays,
+		 GLenum key, unsigned index )
+{
+    unsigned  i;
+
+    for ( i = 0 ; i < arrays->num_arrays ; i++ ) {
+	if ( (arrays->arrays[i].key == key)
+	     && (arrays->arrays[i].index == index) ) {
+	    return & arrays->arrays[i];
+	}
+    }
+    
+    return NULL;
+}
+
+
+static GLboolean
+allocate_array_info_cache( struct array_state_vector * arrays,
+			   size_t required_size )
+{
+    if ( arrays->array_info_cache_buffer_size < required_size ) {
+	GLubyte * temp = realloc( arrays->array_info_cache, required_size + 20 );
+
+	if ( temp == NULL ) {
+	    return GL_FALSE;
+	}
+
+	arrays->large_header = temp;
+	arrays->array_info_cache = temp + 20;
+	arrays->array_info_cache_buffer_size = required_size;
+    }
+
+    arrays->array_info_cache_size = required_size;
+    return GL_TRUE;
+}
+
+
+/**
+ */
+void
+fill_array_info_cache( struct array_state_vector * arrays )
+{
+    GLboolean old_DrawArrays_possible;
+    unsigned  i;
+
+
+    /* Determine how many arrays are enabled.
+     */
+
+    arrays->enabled_array_count = 0;
+    old_DrawArrays_possible = arrays->old_DrawArrays_possible;
+    for ( i = 0 ; i < arrays->num_arrays ; i++ ) {
+	if ( arrays->arrays[i].enabled ) {
+	    arrays->enabled_array_count++;
+	    old_DrawArrays_possible &= arrays->arrays[i].old_DrawArrays_possible;
+	}
+    }
+    
+    
+    if ( arrays->new_DrawArrays_possible ) {
+	assert( ! arrays->new_DrawArrays_possible );
+    }
+    else if ( old_DrawArrays_possible ) {
+	const size_t required_size = arrays->enabled_array_count * 12;
+	uint32_t * info;
+
+
+	if ( ! allocate_array_info_cache( arrays, required_size ) ) {
+	    return;
+	}
+
+
+	info = (uint32_t *) arrays->array_info_cache;
+	for ( i = 0 ; i < arrays->num_arrays ; i++ ) {
+	    if ( arrays->arrays[i].enabled ) {
+		*(info++) = arrays->arrays[i].data_type;
+		*(info++) = arrays->arrays[i].count;
+		*(info++) = arrays->arrays[i].key;
+	    }
+	}
+
+        arrays->array_info_cache_valid = GL_TRUE;
+	arrays->DrawArrays = emit_DrawArrays_old;
+	arrays->DrawElements = emit_DrawElements_old;
+    }
+    else {
+	arrays->DrawArrays = emit_DrawArrays_none;
+	arrays->DrawElements = emit_DrawElements_none;
+    }
+}
+
+
+/**
+ * Emit a \c glDrawArrays command using the "none" protocol.  That is,
+ * emit immediate-mode commands that are equivalent to the requiested
+ * \c glDrawArrays command.  This is used with servers that don't support
+ * the OpenGL 1.1 / EXT_vertex_arrays DrawArrays protocol or in cases where
+ * vertex state is enabled that is not compatible with that protocol.
+ */
+void
+emit_DrawArrays_none( GLenum mode, GLint first, GLsizei count )
+{
+    __GLXcontext *gc = __glXGetCurrentContext();
+    const __GLXattribute * state = 
+       (const __GLXattribute *)(gc->client_state_private);
+    struct array_state_vector * arrays = state->array_state;
+
+    size_t single_vertex_size;
+    GLubyte * pc;
+    unsigned  i;
+    static const uint16_t begin_cmd[2] = { 8, X_GLrop_Begin };
+    static const uint16_t end_cmd[2]   = { 4, X_GLrop_End };
+
+
+    single_vertex_size = calculate_single_vertex_size_none( arrays );
+
+    pc = gc->pc;
+
+    (void) memcpy( pc, begin_cmd, 4 );
+    *(int *)(pc +  4) = mode;
+
+    pc += 8;
+
+    for ( i = 0 ; i < count ; i++ ) {
+	if ( (pc + single_vertex_size) >= gc->bufEnd ) {
+	    pc = __glXFlushRenderBuffer(gc, gc->pc);
+	}
+
+	pc = emit_element_none( pc, arrays, first + i );
+    }
+
+    if ( (pc + 4) >= gc->bufEnd ) {
+	pc = __glXFlushRenderBuffer(gc, gc->pc);
+    }
+
+    (void) memcpy( pc, end_cmd, 4 );
+    pc += 4;
+
+    gc->pc = pc;
+    if ( gc->pc > gc->limit ) {
+	(void) __glXFlushRenderBuffer(gc, gc->pc);
+    }
+}
+
+
+/**
+ * Emit the header data for the GL 1.1 / EXT_vertex_arrays DrawArrays
+ * protocol.
+ * 
+ * \param gc                    GLX context.
+ * \param arrays                Array state.
+ * \param elements_per_request  Location to store the number of elements that
+ *                              can fit in a single Render / RenderLarge
+ *                              command.
+ * \param total_request         Total number of requests for a RenderLarge
+ *                              command.  If a Render command is used, this
+ *                              will be zero.
+ * \param mode                  Drawing mode.
+ * \param count                 Number of vertices.
+ * 
+ * \returns
+ * A pointer to the buffer for array data.
+ */
+static GLubyte *
+emit_DrawArrays_header_old( __GLXcontext * gc,
+			    struct array_state_vector * arrays,
+			    size_t * elements_per_request,
+			    size_t * total_requests,
+			    GLenum mode, GLsizei count )
+{
+    size_t command_size;
+    size_t single_vertex_size;
+    const unsigned header_size = 16;
+    unsigned  i;
+    GLubyte * pc;
+
+
+    /* Determine the size of the whole command.  This includes the header,
+     * the ARRAY_INFO data and the array data.  Once this size is calculated,
+     * it will be known whether a Render or RenderLarge command is needed.
+     */
+
+    single_vertex_size = 0;
+    for ( i = 0 ; i < arrays->num_arrays ; i++ ) {
+	if ( arrays->arrays[i].enabled ) {
+	    single_vertex_size += __GLX_PAD( arrays->arrays[i].element_size );
+	}
+    }
+
+    command_size = arrays->array_info_cache_size + header_size 
+      + (single_vertex_size * count);
+
+
+    /* Write the header for either a Render command or a RenderLarge
+     * command.  After the header is written, write the ARRAY_INFO data.
+     */
+
+    if ( command_size > gc->maxSmallRenderCommandSize ) {
+	/* maxSize is the maximum amount of data can be stuffed into a single
+	 * packet.  sz_xGLXRenderReq is added because bufSize is the maximum
+	 * packet size minus sz_xGLXRenderReq.
+	 */
+	const size_t maxSize = (gc->bufSize + sz_xGLXRenderReq)
+	  - sz_xGLXRenderLargeReq;
+	unsigned vertex_requests;
+
+
+	/* Calculate the number of data packets that will be required to send
+	 * the whole command.  To do this, the number of verticies that
+	 * will fit in a single buffer must be calculated.
+	 * 
+	 * The important value here is elements_per_request.  This is the
+	 * number of complete array elements that will fit in a single
+	 * buffer.  There may be some wasted space at the end of the buffer,
+	 * but splitting elements across buffer boundries would be painful.
+	 */
+
+	elements_per_request[0] = maxSize / single_vertex_size;
+
+	vertex_requests = (count + elements_per_request[0] - 1)
+	  / elements_per_request[0];
+	  
+	*total_requests = vertex_requests + 1;
+
+
+	__glXFlushRenderBuffer(gc, gc->pc);
+
+	command_size += 4;
+
+	pc = arrays->large_header;
+	*(uint32_t *)(pc +  0) = command_size;
+	*(uint32_t *)(pc +  4) = X_GLrop_DrawArrays;
+	*(uint32_t *)(pc +  8) = count;
+	*(uint32_t *)(pc + 12) = arrays->enabled_array_count;
+	*(uint32_t *)(pc + 16) = mode;
+
+	__glXSendLargeChunk( gc, 1, *total_requests, pc,
+			     header_size + 4 + arrays->array_info_cache_size );
+
+	pc = gc->pc;
+    }
+    else {
+	if ( (gc->pc + command_size) >= gc->bufEnd ) {
+	    (void) __glXFlushRenderBuffer(gc, gc->pc);
+	}
+
+	pc = gc->pc;
+	*(uint16_t *)(pc +  0) = command_size;
+	*(uint16_t *)(pc +  2) = X_GLrop_DrawArrays;
+	*(uint32_t *)(pc +  4) = count;
+	*(uint32_t *)(pc +  8) = arrays->enabled_array_count;
+	*(uint32_t *)(pc + 12) = mode;
+
+	pc += header_size;
+
+	(void) memcpy( pc, arrays->array_info_cache,
+		       arrays->array_info_cache_size );
+	pc += arrays->array_info_cache_size;
+	
+	*elements_per_request = count;
+	*total_requests = 0;
+    }
+
+
+    return pc;
+}
+
+
+/**
+ */
+void
+emit_DrawArrays_old( GLenum mode, GLint first, GLsizei count )
+{
+    __GLXcontext *gc = __glXGetCurrentContext();
+    const __GLXattribute * state = 
+       (const __GLXattribute *)(gc->client_state_private);
+    struct array_state_vector * arrays = state->array_state;
+
+    GLubyte * pc;
+    size_t elements_per_request;
+    unsigned total_requests = 0;
+    unsigned i;
+    size_t total_sent = 0;
+
+
+    pc = emit_DrawArrays_header_old( gc, arrays, & elements_per_request,
+				     & total_requests, mode, count);
+
+    
+    /* Write the arrays.
+     */
+
+    if ( total_requests == 0 ) {
+	assert( elements_per_request >= count );
+
+	for ( i = 0 ; i < count ; i++ ) {
+	    pc = emit_element_old( pc, arrays, i + first );
+	}
+
+	assert( pc <= gc->bufEnd );
+
+	gc->pc = pc;
+	if ( gc->pc > gc->limit ) {
+	    (void) __glXFlushRenderBuffer(gc, gc->pc);
+	}
+    }
+    else {
+	unsigned req;
+
+
+	for ( req = 2 ; req <= total_requests ; req++ ) {
+	    if ( count < elements_per_request ) {
+		elements_per_request = count;
+	    }
+
+	    pc = gc->pc;
+	    for ( i = 0 ; i < elements_per_request ; i++ ) {
+		pc = emit_element_old( pc, arrays, i + first );
+	    }
+
+	    first += elements_per_request;
+
+	    total_sent += (size_t) (pc - gc->pc);
+	    __glXSendLargeChunk( gc, req, total_requests, gc->pc,
+				 pc - gc->pc );
+
+	    count -= elements_per_request;
+	}
+    }
+}
+
+
+void
+emit_DrawElements_none( GLenum mode, GLsizei count, GLenum type,
+			const GLvoid *indices )
+{
+    __GLXcontext *gc = __glXGetCurrentContext();
+    const __GLXattribute * state = 
+       (const __GLXattribute *)(gc->client_state_private);
+    struct array_state_vector * arrays = state->array_state;
+    static const uint16_t begin_cmd[2] = { 8, X_GLrop_Begin };
+    static const uint16_t end_cmd[2]   = { 4, X_GLrop_End };
+
+    GLubyte * pc;
+    size_t single_vertex_size;
+    unsigned  i;
+
+
+    single_vertex_size = calculate_single_vertex_size_none( arrays );
+
+
+    if ( (gc->pc + single_vertex_size) >= gc->bufEnd ) {
+	gc->pc = __glXFlushRenderBuffer(gc, gc->pc);
+    }
+
+    pc = gc->pc;
+
+    (void) memcpy( pc, begin_cmd, 4 );
+    *(int *)(pc +  4) = mode;
+
+    pc += 8;
+
+    for ( i = 0 ; i < count ; i++ ) {
+	unsigned  index;
+
+	if ( (pc + single_vertex_size) >= gc->bufEnd ) {
+	    pc = __glXFlushRenderBuffer(gc, gc->pc);
+	}
+
+	switch( type ) {
+	case GL_UNSIGNED_INT:
+	    index = (unsigned) (((GLuint *) indices)[i]);
+	    break;
+	case GL_UNSIGNED_SHORT:
+	    index = (unsigned) (((GLushort *) indices)[i]);
+	    break;
+	case GL_UNSIGNED_BYTE:
+	    index = (unsigned) (((GLubyte *) indices)[i]);
+	    break;
+	}
+	pc = emit_element_none( pc, arrays, index );
+    }
+
+    if ( (pc + 4) >= gc->bufEnd ) {
+	pc = __glXFlushRenderBuffer(gc, gc->pc);
+    }
+
+    (void) memcpy( pc, end_cmd, 4 );
+    pc += 4;
+
+    gc->pc = pc;
+    if ( gc->pc > gc->limit ) {
+	(void) __glXFlushRenderBuffer(gc, gc->pc);
+    }
+}
+
+
+/**
+ */
+void
+emit_DrawElements_old( GLenum mode, GLsizei count, GLenum type,
+		       const GLvoid *indices )
+{
+    __GLXcontext *gc = __glXGetCurrentContext();
+    const __GLXattribute * state = 
+       (const __GLXattribute *)(gc->client_state_private);
+    struct array_state_vector * arrays = state->array_state;
+
+    GLubyte * pc;
+    size_t elements_per_request;
+    unsigned total_requests = 0;
+    unsigned i;
+    unsigned req;
+    const GLuint   * ui_ptr = (const GLuint   *) indices;
+    const GLushort * us_ptr = (const GLushort *) indices;
+    const GLubyte  * ub_ptr = (const GLubyte  *) indices;
+
+
+    pc = emit_DrawArrays_header_old( gc, arrays, & elements_per_request,
+				     & total_requests, mode, count);
+
+    
+    /* Write the arrays.
+     */
+
+    req = 2;
+    while ( count > 0 ) {
+	if ( count < elements_per_request ) {
+	    elements_per_request = count;
+	}
+
+	switch( type ) {
+	case GL_UNSIGNED_INT:
+	    for ( i = 0 ; i < elements_per_request ; i++ ) {
+		const GLint index = (GLint) *(ui_ptr++);
+		pc = emit_element_old( pc, arrays, index );
+	    }
+	    break;
+	case GL_UNSIGNED_SHORT:
+	    for ( i = 0 ; i < elements_per_request ; i++ ) {
+		const GLint index = (GLint) *(us_ptr++);
+		pc = emit_element_old( pc, arrays, index );
+	    }
+	    break;
+	case GL_UNSIGNED_BYTE:
+	    for ( i = 0 ; i < elements_per_request ; i++ ) {
+		const GLint index = (GLint) *(ub_ptr++);
+		pc = emit_element_old( pc, arrays, index );
+	    }
+	    break;
+	}
+
+	if ( total_requests != 0 ) {
+	    __glXSendLargeChunk( gc, req, total_requests, gc->pc,
+				 pc - gc->pc );
+	    pc = gc->pc;
+	    req++;
+	}
+
+	count -= elements_per_request;
+    }
+
+
+    assert( (total_requests == 0) || ((req - 1) == total_requests) );
+
+    if ( total_requests == 0 ) {
+	assert( pc <= gc->bufEnd );
+
+	gc->pc = pc;
+	if ( gc->pc > gc->limit ) {
+	    (void) __glXFlushRenderBuffer(gc, gc->pc);
+	}
+    }
+}
+
+
+/**
+ * Validate that the \c mode parameter to \c glDrawArrays, et. al. is valid.
+ * If it is not valid, then an error code is set in the GLX context.
+ * 
+ * \returns
+ * \c GL_TRUE if the argument is valid, \c GL_FALSE if is not.
+ */
+static GLboolean
+validate_mode(__GLXcontext *gc, GLenum mode)
+{
+    switch(mode) {
+      case GL_POINTS:
+      case GL_LINE_STRIP:
+      case GL_LINE_LOOP:
+      case GL_LINES:
+      case GL_TRIANGLE_STRIP:
+      case GL_TRIANGLE_FAN:
+      case GL_TRIANGLES:
+      case GL_QUAD_STRIP:
+      case GL_QUADS:
+      case GL_POLYGON:
+	break;
+      default:
+        __glXSetError(gc, GL_INVALID_ENUM);
+        return GL_FALSE;
+    }
+    
+    return GL_TRUE;
+}
+
+
+/**
+ * Validate that the \c count parameter to \c glDrawArrays, et. al. is valid.
+ * A value less than zero is invalid and will result in \c GL_INVALID_VALUE
+ * being set.  A value of zero will not result in an error being set, but
+ * will result in \c GL_FALSE being returned.
+ * 
+ * \returns
+ * \c GL_TRUE if the argument is valid, \c GL_FALSE if it is not.
+ */
+static GLboolean
+validate_count(__GLXcontext *gc, GLsizei count)
+{
+    if (count < 0) {
+	__glXSetError(gc, GL_INVALID_VALUE);
+    }
+
+    return (count > 0);
+}
+
+
+void __indirect_glDrawArrays(GLenum mode, GLint first, GLsizei count)
+{
+    __GLXcontext *gc = __glXGetCurrentContext();
+    const __GLXattribute * state = 
+       (const __GLXattribute *)(gc->client_state_private);
+    struct array_state_vector * arrays = state->array_state;
+    
+
+    if ( validate_mode(gc, mode) && validate_count(gc, count) ) {
+	if ( ! arrays->array_info_cache_valid ) {
+	    fill_array_info_cache( arrays );
+	}
+
+	arrays->DrawArrays(mode, first, count);
+    }
+}
+
+
+void __indirect_glArrayElement(GLint index)
+{
+    __GLXcontext *gc = __glXGetCurrentContext();
+    const __GLXattribute * state = 
+       (const __GLXattribute *)(gc->client_state_private);
+    struct array_state_vector * arrays = state->array_state;
+
+    size_t single_vertex_size;
+
+
+    single_vertex_size = calculate_single_vertex_size_none( arrays );
+
+    if ( (gc->pc + single_vertex_size) >= gc->bufEnd ) {
+	gc->pc = __glXFlushRenderBuffer(gc, gc->pc);
+    }
+
+    gc->pc = emit_element_none( gc->pc, arrays, index );
+
+    if ( gc->pc > gc->limit ) {
+	(void) __glXFlushRenderBuffer(gc, gc->pc);
+    }
+}
+
+
+void __indirect_glDrawElements(GLenum mode, GLsizei count, GLenum type,
+		    const GLvoid *indices)
+{
+    __GLXcontext *gc = __glXGetCurrentContext();
+    const __GLXattribute * state = 
+       (const __GLXattribute *)(gc->client_state_private);
+    struct array_state_vector * arrays = state->array_state;
+
+
+    if ( validate_mode(gc, mode) && validate_count(gc, count)  ) {
+	if ( ! arrays->array_info_cache_valid ) {
+	    fill_array_info_cache( arrays );
+	}
+
+	arrays->DrawElements(mode, count, type, indices);
+    }
+}
+
+
+void __indirect_glDrawRangeElements(GLenum mode, GLuint start, GLuint end,
+				    GLsizei count, GLenum type,
+				    const GLvoid *indices)
+{
+    __GLXcontext *gc = __glXGetCurrentContext();
+    const __GLXattribute * state = 
+       (const __GLXattribute *)(gc->client_state_private);
+    struct array_state_vector * arrays = state->array_state;
+
+
+    if ( validate_mode(gc, mode) && validate_count(gc, count) ) {
+	if (end < start) {
+	    __glXSetError(gc, GL_INVALID_VALUE);
+	    return;
+	}
+
+	if ( ! arrays->array_info_cache_valid ) {
+	    fill_array_info_cache( arrays );
+	}
+
+	arrays->DrawElements(mode, count, type, indices);
+    }
+}
+
+
+void __indirect_glMultiDrawArraysEXT(GLenum mode, GLint *first, GLsizei *count,
+		       GLsizei primcount)
+{
+    __GLXcontext *gc = __glXGetCurrentContext();
+    const __GLXattribute * state = 
+       (const __GLXattribute *)(gc->client_state_private);
+    struct array_state_vector * arrays = state->array_state;
+    GLsizei  i;
+
+
+    if ( validate_mode(gc, mode) ) {
+	if ( ! arrays->array_info_cache_valid ) {
+	    fill_array_info_cache( arrays );
+	}
+
+	for ( i = 0 ; i < primcount ; i++ ) {
+	    if ( validate_count( gc, count[i] ) ) {
+		arrays->DrawArrays(mode, first[i], count[i]);
+	    }
+	}
+    }
+}
+
+
+void __indirect_glMultiDrawElementsEXT(GLenum mode, const GLsizei *count,
+			 GLenum type, const GLvoid ** indices,
+			 GLsizei primcount)
+{
+    __GLXcontext *gc = __glXGetCurrentContext();
+    const __GLXattribute * state = 
+       (const __GLXattribute *)(gc->client_state_private);
+    struct array_state_vector * arrays = state->array_state;
+    GLsizei  i;
+
+
+    if ( validate_mode(gc, mode) ) {
+	if ( ! arrays->array_info_cache_valid ) {
+	    fill_array_info_cache( arrays );
+	}
+
+	for ( i = 0 ; i < primcount ; i++ ) {
+	    if ( validate_count( gc, count[i] ) ) {
+		arrays->DrawElements(mode, count[i], type, indices[i]);
+	    }
+	}
+    }
+}
+
+
+#define COMMON_ARRAY_DATA_INIT(a, PTR, TYPE, STRIDE, COUNT, HDR_SIZE, OPCODE) \
+    do { \
+	(a)->data = PTR; \
+	(a)->data_type = TYPE; \
+	(a)->user_stride = STRIDE; \
+	(a)->count = COUNT; \
+	\
+	(a)->element_size = __glXTypeSize( TYPE ) * COUNT; \
+	(a)->true_stride = (STRIDE == 0) \
+	  ? (a)->element_size : STRIDE; \
+	\
+	(a)->header_size = HDR_SIZE; \
+	((uint16_t *) (a)->header)[0] = __GLX_PAD((a)->header_size + (a)->element_size); \
+	((uint16_t *) (a)->header)[1] = OPCODE; \
+    } while(0)
+
+
+void __indirect_glVertexPointer( GLint size, GLenum type, GLsizei stride,
+				 const GLvoid * pointer )
+{
+    static const uint16_t short_ops[5] = {
+	0, 0, X_GLrop_Vertex2sv, X_GLrop_Vertex3sv, X_GLrop_Vertex4sv
+    };
+    static const uint16_t int_ops[5] = {
+	0, 0, X_GLrop_Vertex2iv, X_GLrop_Vertex3iv, X_GLrop_Vertex4iv
+    };
+    static const uint16_t float_ops[5] = {
+	0, 0, X_GLrop_Vertex2fv, X_GLrop_Vertex3fv, X_GLrop_Vertex4fv
+    };
+    static const uint16_t double_ops[5] = {
+	0, 0, X_GLrop_Vertex2dv, X_GLrop_Vertex3dv, X_GLrop_Vertex4dv
+    };
+    uint16_t opcode;
+    __GLXcontext *gc = __glXGetCurrentContext();
+    __GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
+    struct array_state_vector * arrays = state->array_state;
+    struct array_state * a;
+
+
+    if (size < 2 || size > 4 || stride < 0) {
+        __glXSetError(gc, GL_INVALID_VALUE);
+        return;
+    }
+    
+    switch ( type ) {
+    case GL_SHORT:	opcode = short_ops[size]; break;
+    case GL_INT:	opcode = int_ops[size]; break;
+    case GL_FLOAT:	opcode = float_ops[size]; break;
+    case GL_DOUBLE:	opcode = double_ops[size]; break;
+    default:
+        __glXSetError(gc, GL_INVALID_ENUM);
+        return;
+    }
+
+    a = get_array_entry( arrays, GL_VERTEX_ARRAY, 0 );
+    assert( a != NULL );
+    COMMON_ARRAY_DATA_INIT( a, pointer, type, stride, size, 4, opcode );
+
+    if ( a->enabled ) {
+	arrays->array_info_cache_valid = GL_FALSE;
+    }
+}
+
+
+void __indirect_glNormalPointer( GLenum type, GLsizei stride,
+				 const GLvoid * pointer )
+{
+    uint16_t opcode;
+    __GLXcontext *gc = __glXGetCurrentContext();
+    __GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
+    struct array_state_vector * arrays = state->array_state;
+    struct array_state * a;
+
+
+    if (stride < 0) {
+        __glXSetError(gc, GL_INVALID_VALUE);
+        return;
+    }
+    
+    switch ( type ) {
+    case GL_BYTE:	opcode = X_GLrop_Normal3bv; break;
+    case GL_SHORT:	opcode = X_GLrop_Normal3sv; break;
+    case GL_INT:	opcode = X_GLrop_Normal3iv; break;
+    case GL_FLOAT:	opcode = X_GLrop_Normal3fv; break;
+    case GL_DOUBLE:	opcode = X_GLrop_Normal3dv; break;
+    default:
+        __glXSetError(gc, GL_INVALID_ENUM);
+        return;
+    }
+
+    a = get_array_entry( arrays, GL_NORMAL_ARRAY, 0 );
+    assert( a != NULL );
+    COMMON_ARRAY_DATA_INIT( a, pointer, type, stride, 3, 4, opcode );
+
+    if ( a->enabled ) {
+	arrays->array_info_cache_valid = GL_FALSE;
+    }
+}
+
+
+void __indirect_glColorPointer( GLint size, GLenum type, GLsizei stride,
+				const GLvoid * pointer )
+{
+    static const uint16_t byte_ops[5] = {
+	0, 0, 0, X_GLrop_Color3bv, X_GLrop_Color4bv
+    };
+    static const uint16_t ubyte_ops[5] = {
+	0, 0, 0, X_GLrop_Color3ubv, X_GLrop_Color4ubv
+    };
+    static const uint16_t short_ops[5] = {
+	0, 0, 0, X_GLrop_Color3sv, X_GLrop_Color4sv
+    };
+    static const uint16_t ushort_ops[5] = {
+	0, 0, 0, X_GLrop_Color3usv, X_GLrop_Color4usv
+    };
+    static const uint16_t int_ops[5] = {
+	0, 0, 0, X_GLrop_Color3iv, X_GLrop_Color4iv
+    };
+    static const uint16_t uint_ops[5] = {
+	0, 0, 0, X_GLrop_Color3uiv, X_GLrop_Color4uiv
+    };
+    static const uint16_t float_ops[5] = {
+	0, 0, 0, X_GLrop_Color3fv, X_GLrop_Color4fv
+    };
+    static const uint16_t double_ops[5] = {
+	0, 0, 0, X_GLrop_Color3dv, X_GLrop_Color4dv
+    };
+    uint16_t opcode;
+    __GLXcontext *gc = __glXGetCurrentContext();
+    __GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
+    struct array_state_vector * arrays = state->array_state;
+    struct array_state * a;
+
+
+    if (size < 3 || size > 4 || stride < 0) {
+        __glXSetError(gc, GL_INVALID_VALUE);
+        return;
+    }
+    
+    switch ( type ) {
+    case GL_BYTE:		opcode = byte_ops[size]; break;
+    case GL_UNSIGNED_BYTE:	opcode = ubyte_ops[size]; break;
+    case GL_SHORT:		opcode = short_ops[size]; break;
+    case GL_UNSIGNED_SHORT:	opcode = ushort_ops[size]; break;
+    case GL_INT:		opcode = int_ops[size]; break;
+    case GL_UNSIGNED_INT:	opcode = uint_ops[size]; break;
+    case GL_FLOAT:		opcode = float_ops[size]; break;
+    case GL_DOUBLE:		opcode = double_ops[size]; break;
+    default:
+        __glXSetError(gc, GL_INVALID_ENUM);
+        return;
+    }
+
+    a = get_array_entry( arrays, GL_COLOR_ARRAY, 0 );
+    assert( a != NULL );
+    COMMON_ARRAY_DATA_INIT( a, pointer, type, stride, size, 4, opcode );
+
+    if ( a->enabled ) {
+	arrays->array_info_cache_valid = GL_FALSE;
+    }
+}
+
+
+void __indirect_glIndexPointer( GLenum type, GLsizei stride,
+				const GLvoid * pointer )
+{
+    uint16_t opcode;
+    __GLXcontext *gc = __glXGetCurrentContext();
+    __GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
+    struct array_state_vector * arrays = state->array_state;
+    struct array_state * a;
+
+
+    if (stride < 0) {
+        __glXSetError(gc, GL_INVALID_VALUE);
+        return;
+    }
+    
+    switch ( type ) {
+    case GL_UNSIGNED_BYTE:	opcode = X_GLrop_Indexubv; break;
+    case GL_SHORT:		opcode = X_GLrop_Indexsv; break;
+    case GL_INT:		opcode = X_GLrop_Indexiv; break;
+    case GL_FLOAT:		opcode = X_GLrop_Indexfv; break;
+    case GL_DOUBLE:		opcode = X_GLrop_Indexdv; break;
+    default:
+        __glXSetError(gc, GL_INVALID_ENUM);
+        return;
+    }
+
+    a = get_array_entry( arrays, GL_INDEX_ARRAY, 0 );
+    assert( a != NULL );
+    COMMON_ARRAY_DATA_INIT( a, pointer, type, stride, 1, 4, opcode );
+
+    if ( a->enabled ) {
+	arrays->array_info_cache_valid = GL_FALSE;
+    }
+}
+
+
+void __indirect_glEdgeFlagPointer( GLsizei stride, const GLvoid * pointer )
+{
+    __GLXcontext *gc = __glXGetCurrentContext();
+    __GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
+    struct array_state_vector * arrays = state->array_state;
+    struct array_state * a;
+
+
+    if (stride < 0) {
+        __glXSetError(gc, GL_INVALID_VALUE);
+        return;
+    }
+    
+
+    a = get_array_entry( arrays, GL_EDGE_FLAG_ARRAY, 0 );
+    assert( a != NULL );
+    COMMON_ARRAY_DATA_INIT( a, pointer, GL_UNSIGNED_BYTE, stride, 1, 4, X_GLrop_EdgeFlagv );
+
+    if ( a->enabled ) {
+	arrays->array_info_cache_valid = GL_FALSE;
+    }
+}
+
+
+void __indirect_glTexCoordPointer( GLint size, GLenum type, GLsizei stride,
+				   const GLvoid * pointer )
+{
+    static const uint16_t short_ops[5] = {
+	0, X_GLrop_TexCoord1sv, X_GLrop_TexCoord2sv, X_GLrop_TexCoord3sv, X_GLrop_TexCoord4sv
+    };
+    static const uint16_t int_ops[5] = {
+	0, X_GLrop_TexCoord1iv, X_GLrop_TexCoord2iv, X_GLrop_TexCoord3iv, X_GLrop_TexCoord4iv
+    };
+    static const uint16_t float_ops[5] = {
+	0, X_GLrop_TexCoord1dv, X_GLrop_TexCoord2fv, X_GLrop_TexCoord3fv, X_GLrop_TexCoord4fv
+    };
+    static const uint16_t double_ops[5] = {
+	0, X_GLrop_TexCoord1dv, X_GLrop_TexCoord2dv, X_GLrop_TexCoord3dv, X_GLrop_TexCoord4dv
+    };
+
+    static const uint16_t mshort_ops[5] = {
+	0, X_GLrop_MultiTexCoord1svARB, X_GLrop_MultiTexCoord2svARB, X_GLrop_MultiTexCoord3svARB, X_GLrop_MultiTexCoord4svARB
+    };
+    static const uint16_t mint_ops[5] = {
+	0, X_GLrop_MultiTexCoord1ivARB, X_GLrop_MultiTexCoord2ivARB, X_GLrop_MultiTexCoord3ivARB, X_GLrop_MultiTexCoord4ivARB
+    };
+    static const uint16_t mfloat_ops[5] = {
+	0, X_GLrop_MultiTexCoord1dvARB, X_GLrop_MultiTexCoord2fvARB, X_GLrop_MultiTexCoord3fvARB, X_GLrop_MultiTexCoord4fvARB
+    };
+    static const uint16_t mdouble_ops[5] = {
+	0, X_GLrop_MultiTexCoord1dvARB, X_GLrop_MultiTexCoord2dvARB, X_GLrop_MultiTexCoord3dvARB, X_GLrop_MultiTexCoord4dvARB
+    };
+
+    uint16_t opcode;
+    __GLXcontext *gc = __glXGetCurrentContext();
+    __GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
+    struct array_state_vector * arrays = state->array_state;
+    struct array_state * a;
+    unsigned header_size;
+    unsigned index;
+
+
+    if (size < 1 || size > 4 || stride < 0) {
+        __glXSetError(gc, GL_INVALID_VALUE);
+        return;
+    }
+    
+    index = arrays->active_texture_unit;
+    if ( index == 0 ) {
+	switch ( type ) {
+	case GL_SHORT:		opcode = short_ops[size]; break;
+	case GL_INT:		opcode = int_ops[size]; break;
+	case GL_FLOAT:		opcode = float_ops[size]; break;
+	case GL_DOUBLE:		opcode = double_ops[size]; break;
+	default:
+	    __glXSetError(gc, GL_INVALID_ENUM);
+	    return;
+	}
+
+	header_size = 4;
+    }
+    else {
+	switch ( type ) {
+	case GL_SHORT:		opcode = mshort_ops[size]; break;
+	case GL_INT:		opcode = mint_ops[size]; break;
+	case GL_FLOAT:		opcode = mfloat_ops[size]; break;
+	case GL_DOUBLE:		opcode = mdouble_ops[size]; break;
+	default:
+	    __glXSetError(gc, GL_INVALID_ENUM);
+	    return;
+	}
+
+	header_size = 8;
+    }
+
+    a = get_array_entry( arrays, GL_TEXTURE_COORD_ARRAY, index );
+    assert( a != NULL );
+    COMMON_ARRAY_DATA_INIT( a, pointer, type, stride, size, header_size, opcode );
+
+    if ( a->enabled ) {
+	arrays->array_info_cache_valid = GL_FALSE;
+    }
+}
+
+
+void __indirect_glSecondaryColorPointerEXT( GLint size, GLenum type, GLsizei stride,
+				const GLvoid * pointer )
+{
+    uint16_t opcode;
+    __GLXcontext *gc = __glXGetCurrentContext();
+    __GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
+    struct array_state_vector * arrays = state->array_state;
+    struct array_state * a;
+
+
+    if (size != 3 || stride < 0) {
+        __glXSetError(gc, GL_INVALID_VALUE);
+        return;
+    }
+    
+    switch ( type ) {
+    case GL_BYTE:		opcode = 4126; break;
+    case GL_UNSIGNED_BYTE:	opcode = 4131; break;
+    case GL_SHORT:		opcode = 4127; break;
+    case GL_UNSIGNED_SHORT:	opcode = 4132; break;
+    case GL_INT:		opcode = 4128; break;
+    case GL_UNSIGNED_INT:	opcode = 4133; break;
+    case GL_FLOAT:		opcode = 4129; break;
+    case GL_DOUBLE:		opcode = 4130; break;
+    default:
+        __glXSetError(gc, GL_INVALID_ENUM);
+        return;
+    }
+
+    a = get_array_entry( arrays, GL_SECONDARY_COLOR_ARRAY, 0 );
+    if ( a == NULL ) {
+        __glXSetError(gc, GL_INVALID_OPERATION);
+        return;
+    }
+
+    COMMON_ARRAY_DATA_INIT( a, pointer, type, stride, size, 4, opcode );
+
+    if ( a->enabled ) {
+	arrays->array_info_cache_valid = GL_FALSE;
+    }
+}
+
+
+void __indirect_glFogCoordPointerEXT( GLenum type, GLsizei stride,
+				const GLvoid * pointer )
+{
+    uint16_t opcode;
+    __GLXcontext *gc = __glXGetCurrentContext();
+    __GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
+    struct array_state_vector * arrays = state->array_state;
+    struct array_state * a;
+
+
+    if (stride < 0) {
+        __glXSetError(gc, GL_INVALID_VALUE);
+        return;
+    }
+    
+    switch ( type ) {
+    case GL_FLOAT:		opcode = 4124; break;
+    case GL_DOUBLE:		opcode = 4125; break;
+    default:
+        __glXSetError(gc, GL_INVALID_ENUM);
+        return;
+    }
+
+    a = get_array_entry( arrays, GL_FOG_COORD_ARRAY, 0 );
+    if ( a == NULL ) {
+        __glXSetError(gc, GL_INVALID_OPERATION);
+        return;
+    }
+
+    COMMON_ARRAY_DATA_INIT( a, pointer, type, stride, 1, 4, opcode );
+
+    if ( a->enabled ) {
+	arrays->array_info_cache_valid = GL_FALSE;
+    }
+}
+
+
+void __indirect_glClientActiveTextureARB(GLenum texture)
+{
+    __GLXcontext * const gc = __glXGetCurrentContext();
+    __GLXattribute * const state = (__GLXattribute *)(gc->client_state_private);
+    struct array_state_vector * const arrays = state->array_state;
+    const GLint unit = (GLint) texture - GL_TEXTURE0;
+
+
+    if ( (unit < 0) || (unit > arrays->num_texture_units) ) {
+	__glXSetError(gc, GL_INVALID_ENUM);
+	return;
+    }
+
+    arrays->active_texture_unit = unit;
+}
+
+
+/**
+ */
+GLboolean
+__glXSetArrayEnable( __GLXattribute * state,
+		     GLenum key, unsigned index, GLboolean enable )
+{
+    struct array_state_vector * arrays = state->array_state;
+    struct array_state * a;
+    
+
+    if ( key == GL_TEXTURE_COORD_ARRAY ) {
+	index = arrays->active_texture_unit;
+    }
+
+    a = get_array_entry( arrays, key, index );
+
+    if ( (a != NULL) && (a->enabled != enable) ) {
+	a->enabled = enable;
+	arrays->array_info_cache_valid = GL_FALSE;
+    }
+
+    return (a != NULL);
+}
+
+
+void
+__glXArrayDisableAll( __GLXattribute * state )
+{
+    struct array_state_vector * arrays = state->array_state;
+    unsigned  i;
+
+
+    for ( i = 0 ; i < arrays->num_arrays ; i++ ) {
+	arrays->arrays[i].enabled = GL_FALSE;
+    }
+
+    arrays->array_info_cache_valid = GL_FALSE;
+}
+
+
+/**
+ */
+GLboolean
+__glXGetArrayEnable( const __GLXattribute * const state,
+		     GLenum key, unsigned index, GLintptr * dest )
+{
+    const struct array_state_vector * arrays = state->array_state;
+    const struct array_state * a = get_array_entry( (struct array_state_vector *) arrays,
+						    key, index );
+
+    if ( a != NULL ) {
+	*dest = (GLintptr) a->enabled;
+    }
+
+    return (a != NULL);
+}
+
+
+/**
+ */
+GLboolean
+__glXGetArrayType( const __GLXattribute * const state,
+		     GLenum key, unsigned index, GLintptr * dest )
+{
+    const struct array_state_vector * arrays = state->array_state;
+    const struct array_state * a = get_array_entry( (struct array_state_vector *) arrays,
+						    key, index );
+
+    if ( a != NULL ) {
+	*dest = (GLintptr) a->enabled;
+    }
+
+    return (a != NULL);
+}
+
+
+/**
+ */
+GLboolean
+__glXGetArraySize( const __GLXattribute * const state,
+		     GLenum key, unsigned index, GLintptr * dest )
+{
+    const struct array_state_vector * arrays = state->array_state;
+    const struct array_state * a = get_array_entry( (struct array_state_vector *) arrays,
+						    key, index );
+
+    if ( a != NULL ) {
+	*dest = (GLintptr) a->count;
+    }
+
+    return (a != NULL);
+}
+
+
+/**
+ */
+GLboolean
+__glXGetArrayStride( const __GLXattribute * const state,
+		     GLenum key, unsigned index, GLintptr * dest )
+{
+    const struct array_state_vector * arrays = state->array_state;
+    const struct array_state * a = get_array_entry( (struct array_state_vector *) arrays,
+						    key, index );
+
+    if ( a != NULL ) {
+	*dest = (GLintptr) a->user_stride;
+    }
+
+    return (a != NULL);
+}
+
+
+/**
+ */
+GLboolean
+__glXGetArrayPointer( const __GLXattribute * const state,
+		      GLenum key, unsigned index, void ** dest )
+{
+    const struct array_state_vector * arrays = state->array_state;
+    const struct array_state * a = get_array_entry( (struct array_state_vector *) arrays,
+						    key, index );
+
+
+    if ( a != NULL ) {
+	*dest = a->data;
+    }
+
+    return (a != NULL);
+}
+
+
+/**
+ */
+GLuint
+__glXGetActiveTextureUnit( const __GLXattribute * const state )
+{
+    return state->array_state->active_texture_unit;
+}
+
+
+void
+__glXPushArrayState( __GLXattribute * state )
+{
+    struct array_state_vector * arrays = state->array_state;
+    struct array_stack_state * stack = & arrays->stack[ (arrays->stack_index * arrays->num_arrays)];
+    unsigned  i;
+
+
+    for ( i = 0 ; i < arrays->num_arrays ; i++ ) {
+	stack[i].data = arrays->arrays[i].data;
+	stack[i].data_type = arrays->arrays[i].data_type;
+	stack[i].user_stride = arrays->arrays[i].user_stride;
+	stack[i].count = arrays->arrays[i].count;
+	stack[i].key = arrays->arrays[i].key;
+	stack[i].enabled = arrays->arrays[i].enabled;
+    }
+
+    arrays->active_texture_unit_stack[ arrays->stack_index ] =
+      arrays->active_texture_unit;
+
+    arrays->stack_index++;
+}
+
+
+void
+__glXPopArrayState( __GLXattribute * state )
+{
+    struct array_state_vector * arrays = state->array_state;
+    struct array_stack_state * stack;
+    unsigned  i;
+
+
+    arrays->stack_index--;
+    stack = & arrays->stack[ (arrays->stack_index * arrays->num_arrays) ];
+
+    for ( i = 0 ; i < arrays->num_arrays ; i++ ) {
+	switch ( stack[i].key ) {
+	case GL_NORMAL_ARRAY:
+	    __indirect_glNormalPointer( stack[i].data_type,
+					stack[i].user_stride,
+					stack[i].data );
+	    break;
+	case GL_COLOR_ARRAY:
+	    __indirect_glColorPointer( stack[i].count,
+				       stack[i].data_type,
+				       stack[i].user_stride,
+				       stack[i].data );
+	    break;
+	case GL_INDEX_ARRAY:
+	    __indirect_glIndexPointer( stack[i].data_type,
+				       stack[i].user_stride,
+				       stack[i].data );
+	    break;
+	case GL_EDGE_FLAG_ARRAY:
+	    __indirect_glEdgeFlagPointer( stack[i].user_stride,
+					  stack[i].data );
+	    break;
+	case GL_TEXTURE_COORD_ARRAY:
+	    arrays->active_texture_unit = stack[i].index;
+	    __indirect_glTexCoordPointer( stack[i].count,
+					  stack[i].data_type,
+					  stack[i].user_stride,
+					  stack[i].data );
+	    break;
+	case GL_SECONDARY_COLOR_ARRAY:
+	    __indirect_glSecondaryColorPointerEXT( stack[i].count,
+						   stack[i].data_type,
+						   stack[i].user_stride,
+						   stack[i].data );
+	    break;
+	case GL_FOG_COORDINATE_ARRAY:
+	    __indirect_glFogCoordPointerEXT( stack[i].data_type,
+					     stack[i].user_stride,
+					     stack[i].data );
+	    break;
+
+	}
+	
+	__glXSetArrayEnable( state, stack[i].key, stack[i].index,
+			     stack[i].enabled );
+    }
+
+    arrays->active_texture_unit = arrays->active_texture_unit_stack[ arrays->stack_index ];
+}
diff --git a/src/glx/x11/indirect_vertex_array.h b/src/glx/x11/indirect_vertex_array.h
new file mode 100644
index 0000000..5eae8a5
--- /dev/null
+++ b/src/glx/x11/indirect_vertex_array.h
@@ -0,0 +1,55 @@
+/*
+ * (C) Copyright IBM Corporation 2004, 2005
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
+ * IBM,
+ * AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef INDIRECT_VERTEX_ARRAY_H
+#define INDIRECT_VERTEX_ARRAY_H
+
+extern const GLuint __glXTypeSize_table[16];
+
+#define __glXTypeSize(e) ((((e) & ~0x0f) != 0x1400) \
+    ? 0 : __glXTypeSize_table[ (e) & 0x0f ])
+
+extern void __glXArrayDisableAll( __GLXattribute * state );
+
+extern GLboolean __glXSetArrayEnable( __GLXattribute * state,
+    GLenum key, unsigned index, GLboolean enable );
+
+extern GLboolean __glXGetArrayEnable( const __GLXattribute * const state,
+    GLenum key, unsigned index, GLintptr * dest );
+extern GLboolean __glXGetArraySize( const __GLXattribute * const state,
+    GLenum key, unsigned index, GLintptr * dest );
+extern GLboolean __glXGetArrayType( const __GLXattribute * const state,
+    GLenum key, unsigned index, GLintptr * dest );
+extern GLboolean __glXGetArrayStride( const __GLXattribute * const state,
+    GLenum key, unsigned index, GLintptr * dest );
+extern GLboolean __glXGetArrayPointer( const __GLXattribute * const state,
+    GLenum key, unsigned index, void ** dest );
+
+extern void __glXPushArrayState( __GLXattribute * state );
+extern void __glXPopArrayState( __GLXattribute * state );
+
+extern GLuint __glXGetActiveTextureUnit( const __GLXattribute * const state );
+
+#endif /* INDIRECT_VERTEX_ARRAY_H */
diff --git a/src/glx/x11/single2.c b/src/glx/x11/single2.c
index 9279b56..f4dfd29 100644
--- a/src/glx/x11/single2.c
+++ b/src/glx/x11/single2.c
@@ -35,9 +35,11 @@
 */
 
 #include <stdio.h>
+#include <assert.h>
 #include "glxclient.h"
 #include "packsingle.h"
 #include "glxextensions.h"
+#include "indirect_vertex_array.h"
 
 /* Used for GL_ARB_transpose_matrix */
 static void TransposeMatrixf(GLfloat m[16])
@@ -134,24 +136,106 @@
     return retval;
 }
 
-#define CASE_ARRAY_ENABLE(enum_name,array,dest,gl_type) \
-    case GL_ ## enum_name ## _ARRAY: \
-      *dest = (gl_type) (IS_ARRAY_ENABLED(state, array)); break
-#define CASE_ARRAY_SIZE(enum_name,array,dest,gl_type) \
-    case GL_ ## enum_name ## _ARRAY_SIZE: \
-      *dest = (gl_type) state->vertArray.arrays[array ## _ARRAY].size ; break
-#define CASE_ARRAY_TYPE(enum_name,array,dest,gl_type) \
-    case GL_ ## enum_name ## _ARRAY_TYPE: \
-      *dest = (gl_type) state->vertArray.arrays[array ## _ARRAY].type ; break
-#define CASE_ARRAY_STRIDE(enum_name,array,dest,gl_type) \
-    case GL_ ## enum_name ## _ARRAY_STRIDE: \
-      *dest = (gl_type) state->vertArray.arrays[array ## _ARRAY].stride ; break
 
-#define CASE_ARRAY_ALL(enum_name,array,dest,gl_type) \
-	CASE_ARRAY_ENABLE(enum_name,array,dest,gl_type); \
-	CASE_ARRAY_STRIDE(enum_name,array,dest,gl_type); \
-	CASE_ARRAY_TYPE(enum_name,array,dest,gl_type); \
-	CASE_ARRAY_SIZE(enum_name,array,dest,gl_type)
+/**
+ * Get the selected attribute from the vertex array state vector.
+ * 
+ * \returns
+ * On success \c GL_TRUE is returned.  Otherwise, \c GL_FALSE is returned.
+ */
+static GLboolean
+get_array_data( __GLXattribute * state, GLenum cap, GLintptr * data )
+{
+    GLboolean retval = GL_FALSE;
+    const GLint tex_unit = __glXGetActiveTextureUnit( state );
+
+
+    switch( cap ) {
+    case GL_VERTEX_ARRAY:
+    case GL_NORMAL_ARRAY:
+    case GL_COLOR_ARRAY:
+    case GL_INDEX_ARRAY:
+    case GL_EDGE_FLAG_ARRAY:
+    case GL_SECONDARY_COLOR_ARRAY:
+    case GL_FOG_COORD_ARRAY:
+	retval = __glXGetArrayEnable( state, cap, 0, data );
+	break;
+
+    case GL_VERTEX_ARRAY_SIZE:
+	retval = __glXGetArraySize( state, GL_VERTEX_ARRAY, 0, data );
+	break;
+    case GL_COLOR_ARRAY_SIZE:
+	retval = __glXGetArraySize( state, GL_COLOR_ARRAY, 0, data );
+	break;
+    case GL_SECONDARY_COLOR_ARRAY_SIZE:
+	retval = __glXGetArraySize( state, GL_SECONDARY_COLOR_ARRAY, 0, data );
+	break;
+
+    case GL_VERTEX_ARRAY_TYPE:
+	retval = __glXGetArrayType( state, GL_VERTEX_ARRAY, 0, data );
+	break;
+    case GL_NORMAL_ARRAY_TYPE:
+	retval = __glXGetArrayType( state, GL_NORMAL_ARRAY, 0, data );
+	break;
+    case GL_INDEX_ARRAY_TYPE:
+	retval = __glXGetArrayType( state, GL_INDEX_ARRAY, 0, data );
+	break;
+    case GL_COLOR_ARRAY_TYPE:
+	retval = __glXGetArrayType( state, GL_COLOR_ARRAY, 0, data );
+	break;
+    case GL_SECONDARY_COLOR_ARRAY_TYPE:
+	retval = __glXGetArrayType( state, GL_SECONDARY_COLOR_ARRAY, 0, data );
+	break;
+    case GL_FOG_COORD_ARRAY_TYPE:
+	retval = __glXGetArrayType( state, GL_FOG_COORD_ARRAY, 0, data );
+	break;
+
+    case GL_VERTEX_ARRAY_STRIDE:
+	retval = __glXGetArrayStride( state, GL_VERTEX_ARRAY, 0, data );
+	break;
+    case GL_NORMAL_ARRAY_STRIDE:
+	retval = __glXGetArrayStride( state, GL_NORMAL_ARRAY, 0, data );
+	break;
+    case GL_INDEX_ARRAY_STRIDE:
+	retval = __glXGetArrayStride( state, GL_INDEX_ARRAY, 0, data );
+	break;
+    case GL_EDGE_FLAG_ARRAY_STRIDE:
+	retval = __glXGetArrayStride( state, GL_EDGE_FLAG_ARRAY, 0, data );
+	break;
+    case GL_COLOR_ARRAY_STRIDE:
+	retval = __glXGetArrayStride( state, GL_COLOR_ARRAY, 0, data );
+	break;
+    case GL_SECONDARY_COLOR_ARRAY_STRIDE:
+	retval = __glXGetArrayStride( state, GL_SECONDARY_COLOR_ARRAY, 0, data );
+	break;
+    case GL_FOG_COORD_ARRAY_STRIDE:
+	retval = __glXGetArrayStride( state, GL_FOG_COORD_ARRAY, 0, data );
+	break;
+
+    case GL_TEXTURE_COORD_ARRAY:
+	retval = __glXGetArrayEnable( state, GL_TEXTURE_COORD_ARRAY, tex_unit, data );
+	break;
+    case GL_TEXTURE_COORD_ARRAY_SIZE:
+	retval = __glXGetArraySize( state, GL_TEXTURE_COORD_ARRAY, tex_unit, data );
+	break;
+    case GL_TEXTURE_COORD_ARRAY_TYPE:
+	retval = __glXGetArrayType( state, GL_TEXTURE_COORD_ARRAY, tex_unit, data );
+	break;
+    case GL_TEXTURE_COORD_ARRAY_STRIDE:
+	retval = __glXGetArrayStride( state, GL_TEXTURE_COORD_ARRAY, tex_unit, data );
+	break;
+
+    case GL_MAX_ELEMENTS_VERTICES:
+    case GL_MAX_ELEMENTS_INDICES:
+	retval = GL_TRUE;
+	*data = ~0UL;
+	break;
+    }
+
+    
+    return retval;
+}
+
 
 void __indirect_glGetBooleanv(GLenum val, GLboolean *b)
 {
@@ -173,6 +257,8 @@
 	** Error occured; don't modify user's buffer.
 	*/
     } else {
+	GLintptr data;
+
 	/*
 	** For all the queries listed here, we use the locally stored
 	** values rather than the one returned by the server.  Note that
@@ -180,6 +266,12 @@
 	** find out whether it was legal to make a query (it's illegal,
 	** for example, to call a query between glBegin() and glEnd()).
 	*/
+
+	if ( get_array_data( state, val, & data ) ) {
+	    *b = (GLboolean) data;
+	    return;
+	}
+
 	switch (val) {
 	  case GL_PACK_ROW_LENGTH:
 	    *b = (GLboolean)state->storePack.rowLength;
@@ -229,52 +321,11 @@
 	  case GL_UNPACK_LSB_FIRST:
 	    *b = (GLboolean)state->storeUnpack.lsbFirst;
 	    break;
-
-	  CASE_ARRAY_ALL(VERTEX, vertex, b, GLboolean);
-
-	  CASE_ARRAY_ENABLE(NORMAL, normal, b, GLboolean);
-	  CASE_ARRAY_TYPE(NORMAL, normal, b, GLboolean);
-	  CASE_ARRAY_STRIDE(NORMAL, normal, b, GLboolean);
-
-	  CASE_ARRAY_ALL(COLOR, color, b, GLboolean);
-
-	  CASE_ARRAY_ENABLE(INDEX, index, b, GLboolean);
-	  CASE_ARRAY_TYPE(INDEX, index, b, GLboolean);
-	  CASE_ARRAY_STRIDE(INDEX, index, b, GLboolean);
-
-	  case GL_TEXTURE_COORD_ARRAY:
-	    *b = (GLboolean)IS_TEXARRAY_ENABLED(state, state->vertArray.activeTexture);
-	    break;
-	  case GL_TEXTURE_COORD_ARRAY_SIZE:
-	    *b = (GLboolean)state->vertArray.texCoord[state->vertArray.activeTexture].size;
-	    break;
-	  case GL_TEXTURE_COORD_ARRAY_TYPE:
-	    *b = (GLboolean)state->vertArray.texCoord[state->vertArray.activeTexture].type;
-	    break;
-	  case GL_TEXTURE_COORD_ARRAY_STRIDE:
-	    *b = (GLboolean)state->vertArray.texCoord[state->vertArray.activeTexture].stride;
-	    break;
-
-	  CASE_ARRAY_ENABLE(EDGE_FLAG, edgeFlag, b, GLboolean);
-	  CASE_ARRAY_STRIDE(EDGE_FLAG, edgeFlag, b, GLboolean);
-
-	  CASE_ARRAY_ALL(SECONDARY_COLOR, secondaryColor, b, GLboolean);
-
-	  CASE_ARRAY_ENABLE(FOG_COORD, fogCoord, b, GLboolean);
-	  CASE_ARRAY_TYPE(FOG_COORD, fogCoord, b, GLboolean);
-	  CASE_ARRAY_STRIDE(FOG_COORD, fogCoord, b, GLboolean);
-
-	  case GL_MAX_ELEMENTS_VERTICES:
-	    *b = (GLboolean)state->vertArray.maxElementsVertices;
-	    break;
-	  case GL_MAX_ELEMENTS_INDICES:
-	    *b = (GLboolean)state->vertArray.maxElementsIndices;
-	    break;
 	  case GL_MAX_CLIENT_ATTRIB_STACK_DEPTH:
 	    *b = (GLboolean)__GL_CLIENT_ATTRIB_STACK_DEPTH;
 	    break;
-	  case GL_CLIENT_ACTIVE_TEXTURE_ARB:
-	    *b = (GLboolean)(state->vertArray.activeTexture + GL_TEXTURE0_ARB);
+	  case GL_CLIENT_ACTIVE_TEXTURE:
+	    *b = (GLboolean)(__glXGetActiveTextureUnit(state) + GL_TEXTURE0);
 	    break;
 	  default:
 	    /*
@@ -314,6 +365,8 @@
 	** Error occured; don't modify user's buffer.
 	*/
     } else {
+	GLintptr data;
+
 	/*
 	** For all the queries listed here, we use the locally stored
 	** values rather than the one returned by the server.  Note that
@@ -321,6 +374,12 @@
 	** find out whether it was legal to make a query (it's illegal,
 	** for example, to call a query between glBegin() and glEnd()).
 	*/
+
+	if ( get_array_data( state, val, & data ) ) {
+	    *d = (GLdouble) data;
+	    return;
+	}
+
 	switch (val) {
 	  case GL_PACK_ROW_LENGTH:
 	    *d = (GLdouble)state->storePack.rowLength;
@@ -370,52 +429,11 @@
 	  case GL_UNPACK_LSB_FIRST:
 	    *d = (GLdouble)state->storeUnpack.lsbFirst;
 	    break;
-
-	  CASE_ARRAY_ALL(VERTEX, vertex, d, GLdouble);
-
-	  CASE_ARRAY_ENABLE(NORMAL, normal, d, GLdouble);
-	  CASE_ARRAY_TYPE(NORMAL, normal, d, GLdouble);
-	  CASE_ARRAY_STRIDE(NORMAL, normal, d, GLdouble);
-
-	  CASE_ARRAY_ALL(COLOR, color, d, GLdouble);
-
-	  CASE_ARRAY_ENABLE(INDEX, index, d, GLdouble);
-	  CASE_ARRAY_TYPE(INDEX, index, d, GLdouble);
-	  CASE_ARRAY_STRIDE(INDEX, index, d, GLdouble);
-
-	  case GL_TEXTURE_COORD_ARRAY:
-	    *d = (GLdouble) IS_TEXARRAY_ENABLED(state, state->vertArray.activeTexture);
-	    break;
-	  case GL_TEXTURE_COORD_ARRAY_SIZE:
-	    *d = (GLdouble)state->vertArray.texCoord[state->vertArray.activeTexture].size;
-	    break;
-	  case GL_TEXTURE_COORD_ARRAY_TYPE:
-	    *d = (GLdouble)state->vertArray.texCoord[state->vertArray.activeTexture].type;
-	    break;
-	  case GL_TEXTURE_COORD_ARRAY_STRIDE:
-	    *d = (GLdouble)state->vertArray.texCoord[state->vertArray.activeTexture].stride;
-	    break;
-
-	  CASE_ARRAY_ENABLE(EDGE_FLAG, edgeFlag, d, GLdouble);
-	  CASE_ARRAY_STRIDE(EDGE_FLAG, edgeFlag, d, GLdouble);
-
-	  CASE_ARRAY_ALL(SECONDARY_COLOR, secondaryColor, d, GLdouble);
-
-	  CASE_ARRAY_ENABLE(FOG_COORD, fogCoord, d, GLdouble);
-	  CASE_ARRAY_TYPE(FOG_COORD, fogCoord, d, GLdouble);
-	  CASE_ARRAY_STRIDE(FOG_COORD, fogCoord, d, GLdouble);
-
-	  case GL_MAX_ELEMENTS_VERTICES:
-	    *d = (GLdouble)state->vertArray.maxElementsVertices;
-	    break;
-	  case GL_MAX_ELEMENTS_INDICES:
-	    *d = (GLdouble)state->vertArray.maxElementsIndices;
-	    break;
 	  case GL_MAX_CLIENT_ATTRIB_STACK_DEPTH:
 	    *d = (GLdouble)__GL_CLIENT_ATTRIB_STACK_DEPTH;
 	    break;
-	  case GL_CLIENT_ACTIVE_TEXTURE_ARB:
-	    *d = (GLdouble)(state->vertArray.activeTexture + GL_TEXTURE0_ARB);
+	  case GL_CLIENT_ACTIVE_TEXTURE:
+	    *d = (GLdouble)(__glXGetActiveTextureUnit(state) + GL_TEXTURE0);
 	    break;
 	  default:
 	    /*
@@ -455,6 +473,8 @@
 	** Error occured; don't modify user's buffer.
 	*/
     } else {
+	GLintptr data;
+
 	/*
 	** For all the queries listed here, we use the locally stored
 	** values rather than the one returned by the server.  Note that
@@ -462,6 +482,12 @@
 	** find out whether it was legal to make a query (it's illegal,
 	** for example, to call a query between glBegin() and glEnd()).
 	*/
+
+	if ( get_array_data( state, val, & data ) ) {
+	    *f = (GLfloat) data;
+	    return;
+	}
+
 	switch (val) {
 	  case GL_PACK_ROW_LENGTH:
 	    *f = (GLfloat)state->storePack.rowLength;
@@ -511,52 +537,11 @@
 	  case GL_UNPACK_LSB_FIRST:
 	    *f = (GLfloat)state->storeUnpack.lsbFirst;
 	    break;
-
-	  CASE_ARRAY_ALL(VERTEX, vertex, f, GLfloat);
-
-	  CASE_ARRAY_ENABLE(NORMAL, normal, f, GLfloat);
-	  CASE_ARRAY_TYPE(NORMAL, normal, f, GLfloat);
-	  CASE_ARRAY_STRIDE(NORMAL, normal, f, GLfloat);
-
-	  CASE_ARRAY_ALL(COLOR, color, f, GLfloat);
-
-	  CASE_ARRAY_ENABLE(INDEX, index, f, GLfloat);
-	  CASE_ARRAY_TYPE(INDEX, index, f, GLfloat);
-	  CASE_ARRAY_STRIDE(INDEX, index, f, GLfloat);
-
-	  case GL_TEXTURE_COORD_ARRAY:
-	    *f = (GLfloat) IS_TEXARRAY_ENABLED(state, state->vertArray.activeTexture);
-	    break;
-	  case GL_TEXTURE_COORD_ARRAY_SIZE:
-	    *f = (GLfloat)state->vertArray.texCoord[state->vertArray.activeTexture].size;
-	    break;
-	  case GL_TEXTURE_COORD_ARRAY_TYPE:
-	    *f = (GLfloat)state->vertArray.texCoord[state->vertArray.activeTexture].type;
-	    break;
-	  case GL_TEXTURE_COORD_ARRAY_STRIDE:
-	    *f = (GLfloat)state->vertArray.texCoord[state->vertArray.activeTexture].stride;
-	    break;
-
-	  CASE_ARRAY_ENABLE(EDGE_FLAG, edgeFlag, f, GLfloat);
-	  CASE_ARRAY_STRIDE(EDGE_FLAG, edgeFlag, f, GLfloat);
-
-	  CASE_ARRAY_ALL(SECONDARY_COLOR, secondaryColor, f, GLfloat);
-
-	  CASE_ARRAY_ENABLE(FOG_COORD, fogCoord, f, GLfloat);
-	  CASE_ARRAY_TYPE(FOG_COORD, fogCoord, f, GLfloat);
-	  CASE_ARRAY_STRIDE(FOG_COORD, fogCoord, f, GLfloat);
-
-	  case GL_MAX_ELEMENTS_VERTICES:
-	    *f = (GLfloat)state->vertArray.maxElementsVertices;
-	    break;
-	  case GL_MAX_ELEMENTS_INDICES:
-	    *f = (GLfloat)state->vertArray.maxElementsIndices;
-	    break;
 	  case GL_MAX_CLIENT_ATTRIB_STACK_DEPTH:
 	    *f = (GLfloat)__GL_CLIENT_ATTRIB_STACK_DEPTH;
 	    break;
-	  case GL_CLIENT_ACTIVE_TEXTURE_ARB:
-	    *f = (GLfloat)(state->vertArray.activeTexture + GL_TEXTURE0_ARB);
+	  case GL_CLIENT_ACTIVE_TEXTURE:
+	    *f = (GLfloat)(__glXGetActiveTextureUnit(state) + GL_TEXTURE0);
 	    break;
 	  default:
 	    /*
@@ -596,6 +581,8 @@
 	** Error occured; don't modify user's buffer.
 	*/
     } else {
+	GLintptr data;
+
 	/*
 	** For all the queries listed here, we use the locally stored
 	** values rather than the one returned by the server.  Note that
@@ -603,6 +590,12 @@
 	** find out whether it was legal to make a query (it's illegal,
 	** for example, to call a query between glBegin() and glEnd()).
 	*/
+
+	if ( get_array_data( state, val, & data ) ) {
+	    *i = (GLint) data;
+	    return;
+	}
+
 	switch (val) {
 	  case GL_PACK_ROW_LENGTH:
 	    *i = (GLint)state->storePack.rowLength;
@@ -652,52 +645,11 @@
 	  case GL_UNPACK_LSB_FIRST:
 	    *i = (GLint)state->storeUnpack.lsbFirst;
 	    break;
-
-	  CASE_ARRAY_ALL(VERTEX, vertex, i, GLint);
-
-	  CASE_ARRAY_ENABLE(NORMAL, normal, i, GLint);
-	  CASE_ARRAY_TYPE(NORMAL, normal, i, GLint);
-	  CASE_ARRAY_STRIDE(NORMAL, normal, i, GLint);
-
-	  CASE_ARRAY_ALL(COLOR, color, i, GLint);
-
-	  CASE_ARRAY_ENABLE(INDEX, index, i, GLint);
-	  CASE_ARRAY_TYPE(INDEX, index, i, GLint);
-	  CASE_ARRAY_STRIDE(INDEX, index, i, GLint);
-
-	  case GL_TEXTURE_COORD_ARRAY:
-	    *i = (GLint) IS_TEXARRAY_ENABLED(state, state->vertArray.activeTexture);
-	    break;
-	  case GL_TEXTURE_COORD_ARRAY_SIZE:
-	    *i = (GLint)state->vertArray.texCoord[state->vertArray.activeTexture].size;
-	    break;
-	  case GL_TEXTURE_COORD_ARRAY_TYPE:
-	    *i = (GLint)state->vertArray.texCoord[state->vertArray.activeTexture].type;
-	    break;
-	  case GL_TEXTURE_COORD_ARRAY_STRIDE:
-	    *i = (GLint)state->vertArray.texCoord[state->vertArray.activeTexture].stride;
-	    break;
-
-	  CASE_ARRAY_ENABLE(EDGE_FLAG, edgeFlag, i, GLint);
-	  CASE_ARRAY_STRIDE(EDGE_FLAG, edgeFlag, i, GLint);
-
-	  CASE_ARRAY_ALL(SECONDARY_COLOR, secondaryColor, i, GLint);
-
-	  CASE_ARRAY_ENABLE(FOG_COORD, fogCoord, i, GLint);
-	  CASE_ARRAY_TYPE(FOG_COORD, fogCoord, i, GLint);
-	  CASE_ARRAY_STRIDE(FOG_COORD, fogCoord, i, GLint);
-
-	  case GL_MAX_ELEMENTS_VERTICES:
-	    *i = (GLint)state->vertArray.maxElementsVertices;
-	    break;
-	  case GL_MAX_ELEMENTS_INDICES:
-	    *i = (GLint)state->vertArray.maxElementsIndices;
-	    break;
 	  case GL_MAX_CLIENT_ATTRIB_STACK_DEPTH:
 	    *i = (GLint)__GL_CLIENT_ATTRIB_STACK_DEPTH;
 	    break;
-	  case GL_CLIENT_ACTIVE_TEXTURE_ARB:
-	    *i = (GLint)(state->vertArray.activeTexture + GL_TEXTURE0_ARB);
+	  case GL_CLIENT_ACTIVE_TEXTURE:
+	    *i = (GLint)(__glXGetActiveTextureUnit(state) + GL_TEXTURE0);
 	    break;
 	  default:
 	    /*
@@ -981,26 +933,28 @@
     __GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
     xGLXSingleReply reply;
     GLboolean retval = 0;
+    GLintptr enable;
 
     if (!dpy) return 0;
 
     switch(cap) {
-      case GL_VERTEX_ARRAY:
-	  return IS_ARRAY_ENABLED(state, vertex);
-      case GL_NORMAL_ARRAY:
-	  return IS_ARRAY_ENABLED(state, normal);
-      case GL_COLOR_ARRAY:
-	  return IS_ARRAY_ENABLED(state, color);
-      case GL_INDEX_ARRAY:
-	  return IS_ARRAY_ENABLED(state, index);
-      case GL_TEXTURE_COORD_ARRAY:
-	  return IS_TEXARRAY_ENABLED(state, state->vertArray.activeTexture);
-      case GL_EDGE_FLAG_ARRAY:
-	  return IS_ARRAY_ENABLED(state, edgeFlag);
-      case GL_SECONDARY_COLOR_ARRAY:
-	  return IS_ARRAY_ENABLED(state, secondaryColor);
-      case GL_FOG_COORD_ARRAY:
-	  return IS_ARRAY_ENABLED(state, fogCoord);
+    case GL_VERTEX_ARRAY:
+    case GL_NORMAL_ARRAY:
+    case GL_COLOR_ARRAY:
+    case GL_INDEX_ARRAY:
+    case GL_EDGE_FLAG_ARRAY:
+    case GL_SECONDARY_COLOR_ARRAY:
+    case GL_FOG_COORD_ARRAY:
+	retval = __glXGetArrayEnable( state, cap, 0, & enable );
+	assert( retval );
+	return (GLboolean) enable;
+	break;
+    case GL_TEXTURE_COORD_ARRAY:
+	retval = __glXGetArrayEnable( state, GL_TEXTURE_COORD_ARRAY,
+				      __glXGetActiveTextureUnit( state ), & enable );
+	assert( retval );
+	return (GLboolean) enable;
+	break;
     }
 
     __GLX_SINGLE_LOAD_VARIABLES();
@@ -1021,37 +975,32 @@
     if (!dpy) return;
 
     switch(pname) {
-      case GL_VERTEX_ARRAY_POINTER:
-	  *params = (void *)state->vertArray.arrays[ vertex_ARRAY ].ptr;
-	  return;
-      case GL_NORMAL_ARRAY_POINTER:
-	  *params = (void *)state->vertArray.arrays[ normal_ARRAY ].ptr;
-	  return;
-      case GL_COLOR_ARRAY_POINTER:
-	  *params = (void *)state->vertArray.arrays[ color_ARRAY ].ptr;
-	  return;
-      case GL_INDEX_ARRAY_POINTER:
-	  *params = (void *)state->vertArray.arrays[ index_ARRAY ].ptr;
-	  return;
-      case GL_TEXTURE_COORD_ARRAY_POINTER:
-	  *params = (void *)state->vertArray.texCoord[state->vertArray.activeTexture].ptr;
-	  return;
-      case GL_EDGE_FLAG_ARRAY_POINTER:
-	  *params = (void *)state->vertArray.arrays[ edgeFlag_ARRAY ].ptr;
+    case GL_VERTEX_ARRAY_POINTER:
+    case GL_NORMAL_ARRAY_POINTER:
+    case GL_COLOR_ARRAY_POINTER:
+    case GL_INDEX_ARRAY_POINTER:
+    case GL_EDGE_FLAG_ARRAY_POINTER:
+	__glXGetArrayPointer( state, pname - GL_VERTEX_ARRAY_POINTER 
+			      + GL_VERTEX_ARRAY,
+			      0, params );
 	return;
-      case GL_SECONDARY_COLOR_ARRAY_POINTER:
-	  *params = (void *)state->vertArray.arrays[ secondaryColor_ARRAY ].ptr;
+    case GL_TEXTURE_COORD_ARRAY_POINTER:
+	__glXGetArrayPointer( state, GL_TEXTURE_COORD_ARRAY, 
+			      __glXGetActiveTextureUnit( state ), params );
 	return;
-      case GL_FOG_COORD_ARRAY_POINTER:
-	  *params = (void *)state->vertArray.arrays[ fogCoord_ARRAY ].ptr;
+    case GL_SECONDARY_COLOR_ARRAY_POINTER:
+    case GL_FOG_COORD_ARRAY_POINTER:
+	__glXGetArrayPointer( state, pname - GL_FOG_COORD_ARRAY_POINTER
+			      + GL_FOG_COORD_ARRAY, 
+			      0, params );
 	return;
-      case GL_FEEDBACK_BUFFER_POINTER:
+    case GL_FEEDBACK_BUFFER_POINTER:
 	*params = (void *)gc->feedbackBuf;
 	return;
-      case GL_SELECTION_BUFFER_POINTER:
+    case GL_SELECTION_BUFFER_POINTER:
 	*params = (void *)gc->selectBuf;
 	return;
-      default:
+    default:
 	__glXSetError(gc, GL_INVALID_ENUM);
 	return;
     }
diff --git a/src/glx/x11/vertarr.c b/src/glx/x11/vertarr.c
index 5da30a3..77c5146 100644
--- a/src/glx/x11/vertarr.c
+++ b/src/glx/x11/vertarr.c
@@ -34,134 +34,10 @@
 **
 */
 
-#include <assert.h>
 #include "glxclient.h"
-#include "packrender.h"
 #include "indirect.h"
-#include <string.h>
-#include <limits.h>		/* INT_MAX */
+#include "indirect_vertex_array.h"
 
-/* macros for setting function pointers */
-#define __GL_VERTEX_FUNC(NAME, let) \
-    case GL_##NAME: \
-      if (size == 2) \
-	vertexPointer->proc = (void (*)(const void *))__indirect_glVertex2##let##v; \
-      else if (size == 3) \
-	vertexPointer->proc = (void (*)(const void *))__indirect_glVertex3##let##v; \
-      else if (size == 4) \
-	vertexPointer->proc = (void (*)(const void *))__indirect_glVertex4##let##v; \
-      break
-
-#define __GL_NORMAL_FUNC(NAME, let) \
-    case GL_##NAME: \
-      normalPointer->proc = (void (*)(const void *))__indirect_glNormal3##let##v; \
-      break
-
-#define __GL_COLOR_FUNC(NAME, let) \
-    case GL_##NAME: \
-      if (size == 3) \
-	colorPointer->proc = (void (*)(const void *))__indirect_glColor3##let##v; \
-      else if (size == 4)\
-	colorPointer->proc = (void (*)(const void *))__indirect_glColor4##let##v; \
-      break
-
-#define __GL_SEC_COLOR_FUNC(NAME, let) \
-    case GL_##NAME: \
-      seccolorPointer->proc = (void (*)(const void *))__indirect_glSecondaryColor3##let##vEXT; \
-
-#define __GL_FOG_FUNC(NAME, let) \
-    case GL_##NAME: \
-      fogPointer->proc = (void (*)(const void *))__indirect_glFogCoord##let##vEXT; \
-
-#define __GL_INDEX_FUNC(NAME, let) \
-    case GL_##NAME: \
-      indexPointer->proc = (void (*)(const void *))__indirect_glIndex##let##v; \
-      break
-
-#define __GL_TEXTURE_FUNC(NAME, let) \
-    case GL_##NAME: \
-      if (size == 1) { \
-	texCoordPointer->proc = (void (*)(const void *))__indirect_glTexCoord1##let##v; \
-	texCoordPointer->mtex_proc = (void (*)(GLenum, const void *))__indirect_glMultiTexCoord1##let##vARB; \
-      } else if (size == 2) { \
-	texCoordPointer->proc = (void (*)(const void *))__indirect_glTexCoord2##let##v; \
-	texCoordPointer->mtex_proc = (void (*)(GLenum, const void *))__indirect_glMultiTexCoord2##let##vARB; \
-      } else if (size == 3) { \
-	texCoordPointer->proc = (void (*)(const void *))__indirect_glTexCoord3##let##v; \
-	texCoordPointer->mtex_proc = (void (*)(GLenum, const void *))__indirect_glMultiTexCoord2##let##vARB; \
-      } else if (size == 4) { \
-	texCoordPointer->proc = (void (*)(const void *))__indirect_glTexCoord4##let##v; \
-	texCoordPointer->mtex_proc = (void (*)(GLenum, const void *))__indirect_glMultiTexCoord4##let##vARB; \
-      } break
-
-/**
- * Table of sizes, in bytes, of a GL types.  All of the type enums are be in 
- * the range 0x1400 - 0x140F.  That includes types added by extensions (i.e.,
- * \c GL_HALF_FLOAT_NV).  This elements of this table correspond to the
- * type enums masked with 0x0f.
- * 
- * \notes
- * \c GL_HAVE_FLOAT_NV is not included.  Neither are \c GL_2_BYTES,
- * \c GL_3_BYTES, or \c GL_4_BYTES.
- */
-static const GLuint __glXTypeSize_table[16] = {
-    1, 1, 2, 2, 4, 4, 4, 0, 0, 0, 8, 0, 0, 0, 0, 0
-};
-
-#define __glXTypeSize(e) ((((e) & ~0x0f) != 0x1400) \
-    ? 0 : __glXTypeSize_table[ (e) & 0x0f ])
-
-
-/**
- * Initialize vertex array state for a GLX context.
- * 
- * \param gc  GLX context whose vertex array state is to be initialized.
- * 
- * \todo
- * Someone is going to have to check the spec.  This function takes greate
- * care to initialize the \c size and \c type fields to "correct" values
- * for each array.  I'm not sure this is necessary.  I think it should be
- * acceptable to just \c memset the whole \c arrays and \c texCoord arrays
- * to zero and be done with it.  The spec may say something to the contrary,
- * however.
- */
-void __glXInitVertexArrayState(__GLXcontext *gc)
-{
-    __GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
-    __GLXvertArrayState *va = &state->vertArray;
-    GLint i;
-
-    va->enables = 0;
-    va->texture_enables = 0;
-
-    for ( i = 0 ; i < __GLX_MAX_ARRAYS ; i++ ) {
-	va->arrays[ i ].proc = NULL;
-	va->arrays[ i ].skip = 0;
-	va->arrays[ i ].ptr = 0;
-	va->arrays[ i ].size = 1;
-	va->arrays[ i ].type = GL_FLOAT;
-	va->arrays[ i ].stride = 0;
-    }
-
-    va->arrays[ edgeFlag_ARRAY ].type = GL_UNSIGNED_BYTE;;
-
-    va->arrays[ secondaryColor_ARRAY ].size = 3;
-    va->arrays[ color_ARRAY ].size = 4;
-    va->arrays[ normal_ARRAY ].size = 3;
-    va->arrays[ vertex_ARRAY ].size = 4;
-
-    for ( i = 0 ; i < __GLX_MAX_TEXTURE_UNITS ; i++ ) {
-	va->texCoord[ i ].proc = NULL;
-	va->texCoord[ i ].skip = 0;
-	va->texCoord[ i ].ptr = 0;
-	va->texCoord[ i ].size = 4;
-	va->texCoord[ i ].type = GL_FLOAT;
-	va->texCoord[ i ].stride = 0;
-    }
-
-    va->maxElementsVertices = INT_MAX;
-    va->maxElementsIndices = INT_MAX;
-}
 
 /*****************************************************************************/
 
@@ -214,296 +90,6 @@
 
 /*****************************************************************************/
 
-void __indirect_glVertexPointer(GLint size, GLenum type, GLsizei stride,
-		     const GLvoid *pointer)
-{
-    __GLXcontext *gc = __glXGetCurrentContext();
-    __GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
-    __GLXvertexArrayPointerState *vertexPointer = &state->vertArray.arrays[ vertex_ARRAY ];
-
-    /* Check arguments */
-    if (size < 2 || size > 4 || stride < 0) {
-        __glXSetError(gc, GL_INVALID_VALUE);
-        return;
-    }
-
-    /* Choose appropriate api proc */
-    switch(type) {
-        __GL_VERTEX_FUNC(SHORT, s);
-        __GL_VERTEX_FUNC(INT, i);
-        __GL_VERTEX_FUNC(FLOAT, f);
-        __GL_VERTEX_FUNC(DOUBLE, d);
-      default:
-        __glXSetError(gc, GL_INVALID_ENUM);
-        return;
-    }
-
-    vertexPointer->size = size;
-    vertexPointer->type = type;
-    vertexPointer->stride = stride;
-    vertexPointer->ptr = pointer;
-
-    /* Set internal state */
-    if (stride == 0) {
-	vertexPointer->skip = __glXTypeSize(type) * size;
-    } else {
-	vertexPointer->skip = stride;
-    }
-}
-
-void __indirect_glNormalPointer(GLenum type, GLsizei stride, const GLvoid *pointer)
-{
-    __GLXcontext *gc = __glXGetCurrentContext();
-    __GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
-    __GLXvertexArrayPointerState *normalPointer = &state->vertArray.arrays[ normal_ARRAY ];
-
-    /* Check arguments */
-    if (stride < 0) {
-	__glXSetError(gc, GL_INVALID_VALUE);
-	return;
-    } 
-
-    /* Choose appropriate api proc */
-    switch(type) {
-	__GL_NORMAL_FUNC(BYTE, b);
-	__GL_NORMAL_FUNC(SHORT, s);
-	__GL_NORMAL_FUNC(INT, i);
-	__GL_NORMAL_FUNC(FLOAT, f);
-	__GL_NORMAL_FUNC(DOUBLE, d);
-      default:
-        __glXSetError(gc, GL_INVALID_ENUM);
-        return;
-    }
-
-    normalPointer->type = type;
-    normalPointer->stride = stride;
-    normalPointer->ptr = pointer;
-
-    /* Set internal state */
-    if (stride == 0) {
-	normalPointer->skip = 3 * __glXTypeSize(type);
-    } else {
-	normalPointer->skip = stride;
-    }
-}
-
-void __indirect_glColorPointer(GLint size, GLenum type, GLsizei stride,
-		    const GLvoid *pointer)
-{
-    __GLXcontext *gc = __glXGetCurrentContext();
-    __GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
-    __GLXvertexArrayPointerState *colorPointer = &state->vertArray.arrays[ color_ARRAY ];
-
-    /* Check arguments */
-    if (stride < 0) {
-	__glXSetError(gc, GL_INVALID_VALUE);
-	return;
-    } 
-
-    /* Choose appropriate api proc */
-    switch(type) {
-	__GL_COLOR_FUNC(BYTE, b);
-	__GL_COLOR_FUNC(UNSIGNED_BYTE, ub);
-	__GL_COLOR_FUNC(SHORT, s);
-	__GL_COLOR_FUNC(UNSIGNED_SHORT, us);
-	__GL_COLOR_FUNC(INT, i);
-	__GL_COLOR_FUNC(UNSIGNED_INT, ui);
-	__GL_COLOR_FUNC(FLOAT, f);
-	__GL_COLOR_FUNC(DOUBLE, d);
-      default:
-        __glXSetError(gc, GL_INVALID_ENUM);
-        return;
-    }
-
-    colorPointer->size = size;
-    colorPointer->type = type;
-    colorPointer->stride = stride;
-    colorPointer->ptr = pointer;
-
-    /* Set internal state */
-    if (stride == 0) {
-        colorPointer->skip = size * __glXTypeSize(type);
-    } else {
-        colorPointer->skip = stride;
-    }
-}
-
-void __indirect_glIndexPointer(GLenum type, GLsizei stride, const GLvoid *pointer)
-{
-    __GLXcontext *gc = __glXGetCurrentContext();
-    __GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
-    __GLXvertexArrayPointerState *indexPointer = &state->vertArray.arrays[ index_ARRAY ];
-
-    /* Check arguments */
-    if (stride < 0) {
-        __glXSetError(gc, GL_INVALID_VALUE);
-        return;
-    }
-
-    /* Choose appropriate api proc */
-    switch(type) {
-	__GL_INDEX_FUNC(UNSIGNED_BYTE, ub);
-        __GL_INDEX_FUNC(SHORT, s);
-        __GL_INDEX_FUNC(INT, i);
-        __GL_INDEX_FUNC(FLOAT, f);
-        __GL_INDEX_FUNC(DOUBLE, d);
-      default:
-        __glXSetError(gc, GL_INVALID_ENUM);
-        return;
-    }
-
-    indexPointer->type = type;
-    indexPointer->stride = stride;
-    indexPointer->ptr = pointer;
-
-    /* Set internal state */
-    if (stride == 0) {
-	indexPointer->skip = __glXTypeSize(type);
-    } else {
-	indexPointer->skip = stride;
-    }
-}
-
-void __indirect_glTexCoordPointer(GLint size, GLenum type, GLsizei stride,
-		       const GLvoid *pointer)
-{
-    __GLXcontext *gc = __glXGetCurrentContext();
-    __GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
-    __GLXvertexArrayPointerState *texCoordPointer =
-    	&state->vertArray.texCoord[state->vertArray.activeTexture];
-
-    /* Check arguments */
-    if (size < 1 || size > 4 || stride < 0) {
-	__glXSetError(gc, GL_INVALID_VALUE);
-	return;
-    } 
-
-    /* Choose appropriate api proc */
-    switch(type) {
-	__GL_TEXTURE_FUNC(SHORT, s);
-	__GL_TEXTURE_FUNC(INT, i);
-	__GL_TEXTURE_FUNC(FLOAT, f);
-	__GL_TEXTURE_FUNC(DOUBLE,  d);
-      default:
-        __glXSetError(gc, GL_INVALID_ENUM);
-        return;
-    }
-
-    texCoordPointer->size = size;
-    texCoordPointer->type = type;
-    texCoordPointer->stride = stride;
-    texCoordPointer->ptr = pointer;
-
-    /* Set internal state */
-    if (stride == 0) {
-	texCoordPointer->skip = __glXTypeSize(type) * size;
-    } else {
-	texCoordPointer->skip = stride;
-    }
-}
-
-void __indirect_glEdgeFlagPointer(GLsizei stride, const GLvoid *pointer)
-{
-    __GLXcontext *gc = __glXGetCurrentContext();
-    __GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
-    __GLXvertexArrayPointerState *edgeFlagPointer = &state->vertArray.arrays[ edgeFlag_ARRAY ];
-
-    /* Check arguments */
-    if (stride < 0) {
-	__glXSetError(gc, GL_INVALID_VALUE);
-	return;
-    } 
-
-    /* Choose appropriate api proc */
-    edgeFlagPointer->proc = (void (*)(const void *))__indirect_glEdgeFlagv;
-
-    edgeFlagPointer->stride = stride;
-    edgeFlagPointer->ptr = pointer;
-
-    /* Set internal state */
-    if (stride == 0) {
-	edgeFlagPointer->skip = sizeof(GLboolean);
-    } else {
-	edgeFlagPointer->skip = stride;
-    }
-
-}
-
-void __indirect_glSecondaryColorPointerEXT(GLint size, GLenum type, GLsizei stride,
-			     const GLvoid * pointer )
-{
-    __GLXcontext *gc = __glXGetCurrentContext();
-    __GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
-    __GLXvertexArrayPointerState *seccolorPointer = &state->vertArray.arrays[ secondaryColor_ARRAY ];
-
-    /* Check arguments */
-    if ( (stride < 0) || (size != 3) ) {
-	__glXSetError(gc, GL_INVALID_VALUE);
-	return;
-    } 
-
-    /* Choose appropriate api proc */
-    switch(type) {
-	__GL_SEC_COLOR_FUNC(BYTE, b);
-	__GL_SEC_COLOR_FUNC(UNSIGNED_BYTE, ub);
-	__GL_SEC_COLOR_FUNC(SHORT, s);
-	__GL_SEC_COLOR_FUNC(UNSIGNED_SHORT, us);
-	__GL_SEC_COLOR_FUNC(INT, i);
-	__GL_SEC_COLOR_FUNC(UNSIGNED_INT, ui);
-	__GL_SEC_COLOR_FUNC(FLOAT, f);
-	__GL_SEC_COLOR_FUNC(DOUBLE, d);
-      default:
-        __glXSetError(gc, GL_INVALID_ENUM);
-        return;
-    }
-
-    seccolorPointer->size = size;
-    seccolorPointer->type = type;
-    seccolorPointer->stride = stride;
-    seccolorPointer->ptr = pointer;
-
-    /* Set internal state */
-    if (stride == 0) {
-        seccolorPointer->skip = size * __glXTypeSize(type);
-    } else {
-        seccolorPointer->skip = stride;
-    }
-}
-
-void __indirect_glFogCoordPointerEXT(GLenum type, GLsizei stride, const GLvoid * pointer)
-{
-    __GLXcontext *gc = __glXGetCurrentContext();
-    __GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
-    __GLXvertexArrayPointerState *fogPointer = &state->vertArray.arrays[ fogCoord_ARRAY ];
-
-    /* Check arguments */
-    if (stride < 0) {
-	__glXSetError(gc, GL_INVALID_VALUE);
-	return;
-    } 
-
-    /* Choose appropriate api proc */
-    switch(type) {
-	__GL_FOG_FUNC(FLOAT, f);
-	__GL_FOG_FUNC(DOUBLE, d);
-      default:
-        __glXSetError(gc, GL_INVALID_ENUM);
-        return;
-    }
-
-    fogPointer->size = 1;
-    fogPointer->type = type;
-    fogPointer->stride = stride;
-    fogPointer->ptr = pointer;
-
-    /* Set internal state */
-    if (stride == 0) {
-        fogPointer->skip = __glXTypeSize(type);
-    } else {
-        fogPointer->skip = stride;
-    }
-}
-
 void __indirect_glInterleavedArrays(GLenum format, GLsizei stride, const GLvoid *pointer)
 {
     __GLXcontext *gc = __glXGetCurrentContext();
@@ -642,8 +228,8 @@
 
     trueStride = (stride == 0) ? size : stride;
 
-    state->vertArray.enables = 0;
-    state->vertArray.texture_enables = 0;
+    __glXArrayDisableAll( state );
+
     if (tEnable) {
 	__indirect_glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 	__indirect_glTexCoordPointer(tSize, tType, trueStride, (const char *)pointer);
@@ -659,543 +245,3 @@
     __indirect_glEnableClientState(GL_VERTEX_ARRAY);
     __indirect_glVertexPointer(vSize, vType, trueStride, (const char *)pointer+vOffset);
 }
-
-/*****************************************************************************/
-
-void __indirect_glArrayElement(GLint i)
-{
-    __GLXcontext *gc = __glXGetCurrentContext();
-    __GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
-    __GLXvertArrayState *va = &state->vertArray;
-    GLint j;
-
-
-    if (IS_TEXARRAY_ENABLED(state, 0)) {
-	(*va->texCoord[0].proc)(va->texCoord[0].ptr+i*va->texCoord[0].skip);
-    }
-
-    /* Multitexturing is handled specially because the protocol
-     * requires an extra parameter.
-     */
-    for (j=1; j<__GLX_MAX_TEXTURE_UNITS; ++j) {
-	if (IS_TEXARRAY_ENABLED(state, j)) {
-	    (*va->texCoord[j].mtex_proc)(GL_TEXTURE0 + j, va->texCoord[j].ptr+i*va->texCoord[j].skip);
-	}
-    }
-
-    for ( j = 0 ; j < __GLX_MAX_ARRAYS ; j++ ) {
-	if (IS_ARRAY_ENABLED_BY_INDEX(state, j)) {
-	    (*va->arrays[ j ].proc)(va->arrays[ j ].ptr+i*va->arrays[ j ].skip);
-	}
-    }
-}
-
-
-struct array_info {
-    __GLXdispatchDrawArraysComponentHeader ai;
-    GLsizei bytes;
-    const GLubyte *ptr;
-    GLsizei skip;
-};
-
-
-/**
- * Initialize a \c array_info structure for each array that is enabled in
- * \c state.  Determine how many arrays are enabled, and store the result
- * in \c num_arrays.  Determine how big each vertex is, and store the result
- * in \c total_vertex_size.
- * 
- * \returns The size of the final request.  This is the size, in bytes, of
- * the DrawArrays header, the ARRAY_INFO structures, and all the vertex data.
- * This value \b assumes a \c X_GLXRender command is used.  The true size
- * will be 4 bytes larger if a \c X_GLXRenderLarge command is used.
- */
-static GLuint
-prep_arrays(const __GLXattribute * const state, struct array_info * arrays,
-	    GLint count,
-	    GLsizei *num_arrays, GLsizei *total_vertex_size)
-{
-    GLsizei na = 0;
-    GLsizei vs = 0;
-
-#define ASSIGN_ARRAY_INFO(state, enum_name, arr) \
-    do { \
-	arrays[ na ].ai.datatype = state->vertArray. arr .type ; \
-	arrays[ na ].ai.numVals = state->vertArray. arr .size ; \
-	arrays[ na ].ai.component = GL_ ## enum_name ## _ARRAY; \
-\
-	arrays[ na ].bytes = state->vertArray. arr .size \
-	    * __glXTypeSize( state->vertArray. arr .type ); \
-	arrays[ na ].ptr = state->vertArray. arr .ptr; \
-	arrays[ na ].skip = state->vertArray. arr .skip; \
-\
-	vs += __GLX_PAD(arrays[ na ].bytes); \
-	na++; \
-    } while( 0 )
-
-#define ADD_ARRAY_IF_ENABLED(state, enum_name, arr) \
-    do { if ( IS_ARRAY_ENABLED(state, arr) ) { \
-	ASSIGN_ARRAY_INFO(state, enum_name, arrays[ arr ## _ARRAY ] ); \
-    } } while( 0 )
-    
-    ADD_ARRAY_IF_ENABLED(state, VERTEX, vertex);
-    ADD_ARRAY_IF_ENABLED(state, NORMAL, normal);
-    ADD_ARRAY_IF_ENABLED(state, COLOR, color);
-    ADD_ARRAY_IF_ENABLED(state, SECONDARY_COLOR, secondaryColor);
-    ADD_ARRAY_IF_ENABLED(state, FOG_COORD, fogCoord);
-    ADD_ARRAY_IF_ENABLED(state, EDGE_FLAG, edgeFlag);
-    ADD_ARRAY_IF_ENABLED(state, INDEX, index);
-
-    /* The standard DrawArrays protocol *only* supports a single array of
-     * texture coordinates.
-     */
-    if ( IS_TEXARRAY_ENABLED(state, 0) ) {
-	ASSIGN_ARRAY_INFO(state, TEXTURE_COORD, texCoord[0]);
-    }
-
-    *num_arrays = na;
-    *total_vertex_size = vs;
-
-    return __GLX_PAD((__GLX_COMPONENT_HDR_SIZE * na)
-		     + (vs * count)
-		     + __GLX_DRAWARRAYS_CMD_HDR_SIZE);
-}
-
-
-/**
- * Emits the vertex data for the DrawArrays GLX protocol.
- */
-static GLsizei
-emit_vertex(GLubyte * data, const struct array_info * arrays,
-	    GLsizei num_arrays, GLint element, GLsizei offset)
-{
-    GLint i;
-
-    for ( i = 0 ; i < num_arrays ; i++ ) {
-	(void) memcpy( data + offset,
-		       arrays[i].ptr + (arrays[i].skip * element),
-		       arrays[i].bytes );
-	offset += __GLX_PAD(arrays[i].bytes);
-    }
-
-    return offset;
-}
-
-
-static void
-emit_header(GLubyte * pc, const struct array_info * arrays,
-	    GLsizei num_arrays, GLsizei count, GLenum mode)
-{
-    __GLXdispatchDrawArraysComponentHeader *arrayInfo;
-    GLsizei i;
-
-    __GLX_PUT_LONG(0, count);
-    __GLX_PUT_LONG(4, num_arrays);
-    __GLX_PUT_LONG(8, mode);
-
-    arrayInfo = (__GLXdispatchDrawArraysComponentHeader *)
-	(pc + __GLX_DRAWARRAYS_HDR_SIZE);
-
-
-    /* Write the ARRAY_INFO data.
-     */
-
-    for ( i = 0 ; i < num_arrays ; i++ ) {
-	arrayInfo[i] = arrays[i].ai;
-    }
-}
-
-
-/**
- * Emit GLX DrawArrays protocol using a GLXRender packet.
- */
-static void   
-emit_Render_DrawArrays(__GLXcontext * gc, const struct array_info * arrays,
-		       GLsizei first, GLsizei count, GLsizei num_arrays, GLenum mode,
-		       GLsizei cmdlen, GLsizei total_vertex_size)
-{
-    GLubyte * pc = gc->pc;
-    GLsizei offset;
-    GLsizei i;
-
-    __GLX_BEGIN_VARIABLE(X_GLrop_DrawArrays, cmdlen);
-    emit_header(pc + 4, arrays, num_arrays, count, mode);
-
-
-    /* Write the actual array data.
-     */
-
-    offset = __GLX_DRAWARRAYS_CMD_HDR_SIZE 
-	+ (num_arrays * __GLX_COMPONENT_HDR_SIZE);
-    for ( i = 0 ; i < count ; i++ ) {
-	offset = emit_vertex(pc, arrays, num_arrays, i + first, offset);
-    }
-
-    __GLX_END(cmdlen);
-}
-
-
-/**
- * Emit GLX DrawArrays protocol using a GLXRenderLarge packet.
- */
-static void   
-emit_RenderLarge_DrawArrays(__GLXcontext * gc, const struct array_info * arrays,
-		       GLsizei first, GLsizei count, GLsizei num_arrays, GLenum mode,
-		       GLsizei cmdlen, GLsizei total_vertex_size)
-{
-    GLubyte * pc = gc->pc;
-    GLsizei offset;
-    GLsizei i;
-    GLint maxSize;
-    GLint totalRequests;
-    GLint requestNumber;
-    GLsizei elements_per_request;
-
-
-    /* Calculate the maximum amount of data can be stuffed into a single
-     * packet.  sz_xGLXRenderReq is added because bufSize is the maximum
-     * packet size minus sz_xGLXRenderReq.
-     * 
-     * The important value here is elements_per_request.  This is the number
-     * of complete array elements that will fit in a single buffer.  There
-     * may be some wasted space at the end of the buffer, but splitting
-     * elements across buffer boundries would be painful.
-     */
-
-    maxSize = (gc->bufSize + sz_xGLXRenderReq) - sz_xGLXRenderLargeReq;
-
-    elements_per_request = maxSize / total_vertex_size;
-
-    totalRequests = ((count + (elements_per_request - 1))
-		     / elements_per_request) + 1;
-
-
-    /* Fill in the header data and send it away.
-     */
-
-    __GLX_BEGIN_VARIABLE_LARGE(X_GLrop_DrawArrays, cmdlen+4);
-    emit_header(pc + 8, arrays, num_arrays, count, mode);
-
-    gc->pc = pc + (__GLX_DRAWARRAYS_CMD_HDR_SIZE + 4)
-	    + (__GLX_COMPONENT_HDR_SIZE * num_arrays);
-    __glXSendLargeChunk(gc, 1, totalRequests, gc->buf, gc->pc - gc->buf);
-
-
-    /* Write the actual array data.
-     */
-    offset = 0;
-    requestNumber = 2;
-    for ( i = 0 ; i < count ; i++ ) {
-	if ( i == elements_per_request ) {
-	    __glXSendLargeChunk(gc, requestNumber, totalRequests, 
-				gc->buf, offset);
-	    requestNumber++;
-	    offset = 0;
-
-	    count -= i;
-	    first += i;
-	    i = 0;
-	}
-
-	offset = emit_vertex(gc->buf, arrays, num_arrays, i + first, offset);
-    }
-
-    /* If the buffer isn't empty, emit the last, partial request.
-     */
-    if ( offset != 0 ) {
-	assert(requestNumber == totalRequests);
-	__glXSendLargeChunk(gc, requestNumber, totalRequests, gc->buf, offset);
-    }
-
-    gc->pc = gc->buf;
-}
-
-
-/**
- * Emit DrawArrays protocol.  This function acts as a switch betteen
- * \c emit_Render_DrawArrays and \c emit_RenderLarge_DrawArrays depending
- * on how much array data is to be sent.
- */
-static void
-emit_DrawArraysEXT(const __GLXattribute * const state,
-		   GLint first, GLsizei count, GLenum mode)
-{
-    struct array_info arrays[32];
-    GLsizei num_arrays;
-    GLsizei total_vertex_size;
-     __GLXcontext *gc = __glXGetCurrentContext();
-    GLuint cmdlen;
-
-
-    /* Determine how big the final request will be.  This depends on a number
-     * of factors.  It depends on how many array elemets there are (which is
-     * the passed-in 'count'), how many arrays are enabled, how many elements
-     * are in each array entry, and what the types are for each array.
-     */
-
-    cmdlen = prep_arrays(state, arrays, count, & num_arrays,
-			 & total_vertex_size);
-
-
-    /* If the data payload and the protocol header is too large for a Render
-     * command, use a RenderLarge command.
-     */
-    if (cmdlen > gc->maxSmallRenderCommandSize) {
-	emit_RenderLarge_DrawArrays(gc, arrays, first, count, num_arrays,
-				    mode, cmdlen, total_vertex_size);
-    }
-    else {
-	emit_Render_DrawArrays(gc, arrays, first, count, num_arrays,
-			       mode, cmdlen, total_vertex_size);
-    }
-}
-
-
-/**
- * Emit a DrawArrays call using the old "protocol."  This isn't really
- * DrawArrays protocol at all.  It just simulates DrawArrays by using
- * immediate-mode vertex calls.  Very, very slow for large arrays, but works
- * with every GLX server.
- */
-static void
-emit_DrawArrays_old(const __GLXattribute * const state, 
-		    GLint first, GLsizei count, GLenum mode)
-{
-    const __GLXvertArrayState *va = &state->vertArray;
-    const GLubyte *vaPtr[__GLX_MAX_ARRAYS];
-    const GLubyte *tcaPtr[__GLX_MAX_TEXTURE_UNITS];
-    GLint i, j;
-
-    /*
-    ** Set up pointers for quick array traversal.
-    */
-    
-    (void) memset( vaPtr,  0, sizeof(vaPtr) );
-    (void) memset( tcaPtr, 0, sizeof(tcaPtr) );
-
-    for ( j = 0 ; j < __GLX_MAX_ARRAYS ; j++ ) {
-	if (IS_ARRAY_ENABLED_BY_INDEX(state, j)) {
-	    vaPtr[ j ] = va->arrays[ j ].ptr + first * va->arrays[ j ].skip;
-	}
-    }
-
-    for ( j = 0 ; j < __GLX_MAX_TEXTURE_UNITS ; j++ ) {
-	if (IS_TEXARRAY_ENABLED(state, j)) 
-	    tcaPtr[ j ] = va->texCoord[ j ].ptr + first * va->texCoord[ j ].skip;
-    }
-
-    __indirect_glBegin(mode);
-        for (i = 0; i < count; i++) {
-	    if (IS_TEXARRAY_ENABLED(state, 0)) {
-		(*va->texCoord[0].proc)(tcaPtr[0]);
-		tcaPtr[0] += va->texCoord[0].skip;
-	    }
-
-	    /* Multitexturing is handled specially because the protocol
-	     * requires an extra parameter.
-	     */
-	    for (j=1; j<__GLX_MAX_TEXTURE_UNITS; ++j) {
-		if (IS_TEXARRAY_ENABLED(state, j)) {
-		    (*va->texCoord[j].mtex_proc)(GL_TEXTURE0 + j, tcaPtr[j]);
-		    tcaPtr[j] += va->texCoord[j].skip;
-		}
-	    }
-
-	    for ( j = 0 ; j < __GLX_MAX_ARRAYS ; j++ ) {
-		if (IS_ARRAY_ENABLED_BY_INDEX(state, j)) {
-		    (*va->arrays[ j ].proc)(vaPtr[ j ]);
-		    vaPtr[ j ] += va->arrays[ j ].skip;
-		}
-            }
-        }
-    __indirect_glEnd();
-}
-
-
-/**
- * Validate that the \c mode and \c count parameters to \c glDrawArrays or
- * \c glDrawElements are valid.  If the arguments are not valid, then an
- * error code is set in the GLX context.
- * 
- * \returns \c GL_TRUE if the arguments are valide, \c GL_FALSE if they are
- *          not.
- */
-static GLboolean
-glx_validate_array_args(__GLXcontext *gc, GLenum mode, GLsizei count)
-{
-    switch(mode) {
-      case GL_POINTS:
-      case GL_LINE_STRIP:
-      case GL_LINE_LOOP:
-      case GL_LINES:
-      case GL_TRIANGLE_STRIP:
-      case GL_TRIANGLE_FAN:
-      case GL_TRIANGLES:
-      case GL_QUAD_STRIP:
-      case GL_QUADS:
-      case GL_POLYGON:
-	break;
-      default:
-        __glXSetError(gc, GL_INVALID_ENUM);
-        return GL_FALSE;
-    }
-
-    if (count < 0) {
-	__glXSetError(gc, GL_INVALID_VALUE);
-	return GL_FALSE;
-    }
-
-    return GL_TRUE;
-}
-
-
-void __indirect_glDrawArrays(GLenum mode, GLint first, GLsizei count)
-{
-    __GLXcontext *gc = __glXGetCurrentContext();
-    const __GLXattribute * state = 
-       (const __GLXattribute *)(gc->client_state_private);
-
-
-    if ( ! glx_validate_array_args(gc, mode, count) ) {
-	return;
-    }
-
-    /* The "true" DrawArrays protocol does not support generic attributes,
-     * multiple vertex arrays, or multiple texture coordinate arrays.
-     */
-    if ( state->NoDrawArraysProtocol 
-	 || (state->vertArray.texture_enables > 1) ) {
-	emit_DrawArrays_old(state, first, count, mode);
-    }
-    else {
-	emit_DrawArraysEXT(state, first, count, mode);
-    }
-}
-
-
-/**
- * \todo Modify this to use the "true" DrawArrays protocol if possible.  This
- * would probably require refactoring out parts of \c emit_DrawArraysEXT into
- * more general functions that could be used in either place.
- */
-void __indirect_glDrawElements(GLenum mode, GLsizei count, GLenum type,
-		    const GLvoid *indices)
-{
-    __GLXcontext *gc = __glXGetCurrentContext();
-    __GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
-    __GLXvertArrayState *va = &state->vertArray;
-    const GLubyte *iPtr1 = NULL;
-    const GLushort *iPtr2 = NULL;
-    const GLuint *iPtr3 = NULL;
-    GLint i, j, offset = 0;
-
-    if ( ! glx_validate_array_args(gc, mode, count) ) {
-	return;
-    }
-
-    switch (type) {
-      case GL_UNSIGNED_BYTE:
-	iPtr1 = (const GLubyte *)indices;
-	break;
-      case GL_UNSIGNED_SHORT:
-	iPtr2 = (const GLushort *)indices;
-	break;
-      case GL_UNSIGNED_INT:
-	iPtr3 = (const GLuint *)indices;
-	break;
-      default:
-        __glXSetError(gc, GL_INVALID_ENUM);
-        return;
-    }
-
-    __indirect_glBegin(mode);
-        for (i = 0; i < count; i++) {
-	    switch (type) {
-	      case GL_UNSIGNED_BYTE:
-		offset = (GLint)(*iPtr1++);
-		break;
-	      case GL_UNSIGNED_SHORT:
-		offset = (GLint)(*iPtr2++);
-		break;
-	      case GL_UNSIGNED_INT:
-		offset = (GLint)(*iPtr3++);
-		break;
-	    }
-
-	    if (IS_TEXARRAY_ENABLED(state, 0)) {
-		(*va->texCoord[0].proc)(va->texCoord[0].ptr+
-					(offset*va->texCoord[0].skip));
-	    }
-
-	    /* Multitexturing is handled specially because the protocol
-	     * requires an extra parameter.
-	     */
-	    for (j=1; j<__GLX_MAX_TEXTURE_UNITS; ++j) {
-		if (IS_TEXARRAY_ENABLED(state, j)) {
-		    (*va->texCoord[j].mtex_proc)(GL_TEXTURE0 + j,
-						 va->texCoord[j].ptr+
-						 (offset*va->texCoord[j].skip));
-		}
-	    }
-
-	    for ( j = 0 ; j < __GLX_MAX_ARRAYS ; j++ ) {
-		if (IS_ARRAY_ENABLED_BY_INDEX(state, j)) {
-		    (*va->arrays[ j ].proc)(va->arrays[ j ].ptr
-					    +(offset*va->arrays[ j ].skip));
-		}
-            }
-        }
-    __indirect_glEnd();
-}
-
-void __indirect_glDrawRangeElements(GLenum mode, GLuint start, GLuint end,
-			 GLsizei count, GLenum type,
-			 const GLvoid *indices)
-{
-    __GLXcontext *gc = __glXGetCurrentContext();
-
-    if (end < start) {
-	__glXSetError(gc, GL_INVALID_VALUE);
-	return;
-    }
-
-    __indirect_glDrawElements(mode,count,type,indices);
-}
-
-void __indirect_glMultiDrawArraysEXT(GLenum mode, GLint *first, GLsizei *count,
-		       GLsizei primcount)
-{
-   GLsizei  i;
-
-   for(i=0; i<primcount; i++) {
-      if ( count[i] > 0 ) {
-	  __indirect_glDrawArrays( mode, first[i], count[i] );
-      }
-   }
-}
-
-void __indirect_glMultiDrawElementsEXT(GLenum mode, const GLsizei *count,
-			 GLenum type, const GLvoid ** indices,
-			 GLsizei primcount)
-{
-   GLsizei  i;
-
-   for(i=0; i<primcount; i++) {
-      if ( count[i] > 0 ) {
-	  __indirect_glDrawElements( mode, count[i], type, indices[i] );
-      }
-   }
-}
-
-void __indirect_glClientActiveTextureARB(GLenum texture)
-{
-    __GLXcontext *gc = __glXGetCurrentContext();
-    __GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
-    GLint unit = (GLint) texture - GL_TEXTURE0;
-
-    if (unit < 0 || __GLX_MAX_TEXTURE_UNITS <= unit) {
-	__glXSetError(gc, GL_INVALID_ENUM);
-	return;
-    }
-    state->vertArray.activeTexture = unit;
-}