1cdc920a0Smrg/*
2cdc920a0Smrg * (C) Copyright IBM Corporation 2004, 2005
3cdc920a0Smrg * All Rights Reserved.
4cdc920a0Smrg *
5cdc920a0Smrg * Permission is hereby granted, free of charge, to any person obtaining a
6cdc920a0Smrg * copy of this software and associated documentation files (the "Software"),
7cdc920a0Smrg * to deal in the Software without restriction, including without limitation
8cdc920a0Smrg * the rights to use, copy, modify, merge, publish, distribute, sub license,
9cdc920a0Smrg * and/or sell copies of the Software, and to permit persons to whom the
10cdc920a0Smrg * Software is furnished to do so, subject to the following conditions:
11cdc920a0Smrg *
12cdc920a0Smrg * The above copyright notice and this permission notice (including the next
13cdc920a0Smrg * paragraph) shall be included in all copies or substantial portions of the
14cdc920a0Smrg * Software.
15cdc920a0Smrg *
16cdc920a0Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17cdc920a0Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18cdc920a0Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
19cdc920a0Smrg * IBM,
20cdc920a0Smrg * AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21cdc920a0Smrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
22cdc920a0Smrg * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23cdc920a0Smrg * SOFTWARE.
24cdc920a0Smrg */
25cdc920a0Smrg
26cdc920a0Smrg#include <inttypes.h>
27cdc920a0Smrg#include <assert.h>
28cdc920a0Smrg#include <string.h>
29cdc920a0Smrg
307ec681f3Smrg#include "util/compiler.h"
317ec681f3Smrg
32cdc920a0Smrg#include "glxclient.h"
33cdc920a0Smrg#include "indirect.h"
34cdc920a0Smrg#include <GL/glxproto.h>
35cdc920a0Smrg#include "glxextensions.h"
36cdc920a0Smrg#include "indirect_vertex_array.h"
37cdc920a0Smrg#include "indirect_vertex_array_priv.h"
38cdc920a0Smrg
39cdc920a0Smrg#define __GLX_PAD(n) (((n)+3) & ~3)
40cdc920a0Smrg
41cdc920a0Smrg/**
42cdc920a0Smrg * \file indirect_vertex_array.c
43cdc920a0Smrg * Implement GLX protocol for vertex arrays and vertex buffer objects.
44cdc920a0Smrg *
45cdc920a0Smrg * The most important function in this fill is \c fill_array_info_cache.
46cdc920a0Smrg * The \c array_state_vector contains a cache of the ARRAY_INFO data sent
47cdc920a0Smrg * in the DrawArrays protocol.  Certain operations, such as enabling or
48cdc920a0Smrg * disabling an array, can invalidate this cache.  \c fill_array_info_cache
49cdc920a0Smrg * fills-in this data.  Additionally, it examines the enabled state and
50cdc920a0Smrg * other factors to determine what "version" of DrawArrays protocoal can be
51cdc920a0Smrg * used.
52cdc920a0Smrg *
53cdc920a0Smrg * Current, only two versions of DrawArrays protocol are implemented.  The
54cdc920a0Smrg * first version is the "none" protocol.  This is the fallback when the
55cdc920a0Smrg * server does not support GL 1.1 / EXT_vertex_arrays.  It is implemented
56cdc920a0Smrg * by sending batches of immediate mode commands that are equivalent to the
57cdc920a0Smrg * DrawArrays protocol.
58cdc920a0Smrg *
59cdc920a0Smrg * The other protocol that is currently implemented is the "old" protocol.
60cdc920a0Smrg * This is the GL 1.1 DrawArrays protocol.  The only difference between GL
61cdc920a0Smrg * 1.1 and EXT_vertex_arrays is the opcode used for the DrawArrays command.
62cdc920a0Smrg * This protocol is called "old" because the ARB is in the process of
63cdc920a0Smrg * defining a new protocol, which will probably be called wither "new" or
64cdc920a0Smrg * "vbo", to support multiple texture coordinate arrays, generic attributes,
65cdc920a0Smrg * and vertex buffer objects.
66cdc920a0Smrg *
67cdc920a0Smrg * \author Ian Romanick <ian.d.romanick@intel.com>
68cdc920a0Smrg */
69cdc920a0Smrg
70cdc920a0Smrgstatic void emit_DrawArrays_none(GLenum mode, GLint first, GLsizei count);
71cdc920a0Smrgstatic void emit_DrawArrays_old(GLenum mode, GLint first, GLsizei count);
72cdc920a0Smrg
73cdc920a0Smrgstatic void emit_DrawElements_none(GLenum mode, GLsizei count, GLenum type,
74cdc920a0Smrg                                   const GLvoid * indices);
75cdc920a0Smrgstatic void emit_DrawElements_old(GLenum mode, GLsizei count, GLenum type,
76cdc920a0Smrg                                  const GLvoid * indices);
77cdc920a0Smrg
78cdc920a0Smrg
79cdc920a0Smrgstatic GLubyte *emit_element_none(GLubyte * dst,
80cdc920a0Smrg                                  const struct array_state_vector *arrays,
81cdc920a0Smrg                                  unsigned index);
82cdc920a0Smrgstatic GLubyte *emit_element_old(GLubyte * dst,
83cdc920a0Smrg                                 const struct array_state_vector *arrays,
84cdc920a0Smrg                                 unsigned index);
85cdc920a0Smrgstatic struct array_state *get_array_entry(const struct array_state_vector
86cdc920a0Smrg                                           *arrays, GLenum key,
87cdc920a0Smrg                                           unsigned index);
88cdc920a0Smrgstatic void fill_array_info_cache(struct array_state_vector *arrays);
893464ebd5Sriastradhstatic GLboolean validate_mode(struct glx_context * gc, GLenum mode);
903464ebd5Sriastradhstatic GLboolean validate_count(struct glx_context * gc, GLsizei count);
913464ebd5Sriastradhstatic GLboolean validate_type(struct glx_context * gc, GLenum type);
92cdc920a0Smrg
93cdc920a0Smrg
94cdc920a0Smrg/**
95cdc920a0Smrg * Table of sizes, in bytes, of a GL types.  All of the type enums are be in
96cdc920a0Smrg * the range 0x1400 - 0x140F.  That includes types added by extensions (i.e.,
97cdc920a0Smrg * \c GL_HALF_FLOAT_NV).  This elements of this table correspond to the
98cdc920a0Smrg * type enums masked with 0x0f.
99cdc920a0Smrg *
100cdc920a0Smrg * \notes
101cdc920a0Smrg * \c GL_HALF_FLOAT_NV is not included.  Neither are \c GL_2_BYTES,
102cdc920a0Smrg * \c GL_3_BYTES, or \c GL_4_BYTES.
103cdc920a0Smrg */
104cdc920a0Smrgconst GLuint __glXTypeSize_table[16] = {
105cdc920a0Smrg   1, 1, 2, 2, 4, 4, 4, 0, 0, 0, 8, 0, 0, 0, 0, 0
106cdc920a0Smrg};
107cdc920a0Smrg
108cdc920a0Smrg
109cdc920a0Smrg/**
110cdc920a0Smrg * Free the per-context array state that was allocated with
111cdc920a0Smrg * __glXInitVertexArrayState().
112cdc920a0Smrg */
113cdc920a0Smrgvoid
1143464ebd5Sriastradh__glXFreeVertexArrayState(struct glx_context * gc)
115cdc920a0Smrg{
116cdc920a0Smrg   __GLXattribute *state = (__GLXattribute *) (gc->client_state_private);
117cdc920a0Smrg   struct array_state_vector *arrays = state->array_state;
118cdc920a0Smrg
119cdc920a0Smrg   if (arrays) {
120af69d88dSmrg      free(arrays->stack);
121af69d88dSmrg      arrays->stack = NULL;
122af69d88dSmrg      free(arrays->arrays);
123af69d88dSmrg      arrays->arrays = NULL;
124cdc920a0Smrg      free(arrays);
125cdc920a0Smrg      state->array_state = NULL;
126cdc920a0Smrg   }
127cdc920a0Smrg}
128cdc920a0Smrg
129cdc920a0Smrg
130cdc920a0Smrg/**
131cdc920a0Smrg * Initialize vertex array state of a GLX context.
132cdc920a0Smrg *
133cdc920a0Smrg * \param gc  GLX context whose vertex array state is to be initialized.
134cdc920a0Smrg *
135cdc920a0Smrg * \warning
1363464ebd5Sriastradh * This function may only be called after struct glx_context::gl_extension_bits,
1373464ebd5Sriastradh * struct glx_context::server_minor, and __GLXcontext::server_major have been
138cdc920a0Smrg * initialized.  These values are used to determine what vertex arrays are
139cdc920a0Smrg * supported.
140cdc920a0Smrg */
141cdc920a0Smrgvoid
1423464ebd5Sriastradh__glXInitVertexArrayState(struct glx_context * gc)
143cdc920a0Smrg{
144cdc920a0Smrg   __GLXattribute *state = (__GLXattribute *) (gc->client_state_private);
145cdc920a0Smrg   struct array_state_vector *arrays;
146cdc920a0Smrg
147cdc920a0Smrg   unsigned array_count;
148cdc920a0Smrg   int texture_units = 1, vertex_program_attribs = 0;
149cdc920a0Smrg   unsigned i, j;
150cdc920a0Smrg
151cdc920a0Smrg   GLboolean got_fog = GL_FALSE;
152cdc920a0Smrg   GLboolean got_secondary_color = GL_FALSE;
153cdc920a0Smrg
154cdc920a0Smrg
155cdc920a0Smrg   arrays = calloc(1, sizeof(struct array_state_vector));
15601e04c3fSmrg   state->array_state = arrays;
157af69d88dSmrg
158af69d88dSmrg   if (arrays == NULL) {
159af69d88dSmrg      __glXSetError(gc, GL_OUT_OF_MEMORY);
160af69d88dSmrg      return;
161af69d88dSmrg   }
162cdc920a0Smrg
163cdc920a0Smrg   arrays->old_DrawArrays_possible = !state->NoDrawArraysProtocol;
164cdc920a0Smrg   arrays->new_DrawArrays_possible = GL_FALSE;
165cdc920a0Smrg   arrays->DrawArrays = NULL;
166cdc920a0Smrg
167cdc920a0Smrg   arrays->active_texture_unit = 0;
168cdc920a0Smrg
169cdc920a0Smrg
170cdc920a0Smrg   /* Determine how many arrays are actually needed.  Only arrays that
171cdc920a0Smrg    * are supported by the server are create.  For example, if the server
172cdc920a0Smrg    * supports only 2 texture units, then only 2 texture coordinate arrays
173cdc920a0Smrg    * are created.
174cdc920a0Smrg    *
175cdc920a0Smrg    * At the very least, GL_VERTEX_ARRAY, GL_NORMAL_ARRAY,
176cdc920a0Smrg    * GL_COLOR_ARRAY, GL_INDEX_ARRAY, GL_TEXTURE_COORD_ARRAY, and
177cdc920a0Smrg    * GL_EDGE_FLAG_ARRAY are supported.
178cdc920a0Smrg    */
179cdc920a0Smrg
180cdc920a0Smrg   array_count = 5;
181cdc920a0Smrg
182cdc920a0Smrg   if (__glExtensionBitIsEnabled(gc, GL_EXT_fog_coord_bit)
183cdc920a0Smrg       || (gc->server_major > 1) || (gc->server_minor >= 4)) {
184cdc920a0Smrg      got_fog = GL_TRUE;
185cdc920a0Smrg      array_count++;
186cdc920a0Smrg   }
187cdc920a0Smrg
188cdc920a0Smrg   if (__glExtensionBitIsEnabled(gc, GL_EXT_secondary_color_bit)
189cdc920a0Smrg       || (gc->server_major > 1) || (gc->server_minor >= 4)) {
190cdc920a0Smrg      got_secondary_color = GL_TRUE;
191cdc920a0Smrg      array_count++;
192cdc920a0Smrg   }
193cdc920a0Smrg
194cdc920a0Smrg   if (__glExtensionBitIsEnabled(gc, GL_ARB_multitexture_bit)
195cdc920a0Smrg       || (gc->server_major > 1) || (gc->server_minor >= 3)) {
196cdc920a0Smrg      __indirect_glGetIntegerv(GL_MAX_TEXTURE_UNITS, &texture_units);
197cdc920a0Smrg   }
198cdc920a0Smrg
199cdc920a0Smrg   if (__glExtensionBitIsEnabled(gc, GL_ARB_vertex_program_bit)) {
200cdc920a0Smrg      __indirect_glGetProgramivARB(GL_VERTEX_PROGRAM_ARB,
201cdc920a0Smrg                                   GL_MAX_PROGRAM_ATTRIBS_ARB,
202cdc920a0Smrg                                   &vertex_program_attribs);
203cdc920a0Smrg   }
204cdc920a0Smrg
205cdc920a0Smrg   arrays->num_texture_units = texture_units;
206cdc920a0Smrg   arrays->num_vertex_program_attribs = vertex_program_attribs;
207cdc920a0Smrg   array_count += texture_units + vertex_program_attribs;
208cdc920a0Smrg   arrays->num_arrays = array_count;
209cdc920a0Smrg   arrays->arrays = calloc(array_count, sizeof(struct array_state));
210cdc920a0Smrg
211af69d88dSmrg   if (arrays->arrays == NULL) {
21201e04c3fSmrg      state->array_state = NULL;
213af69d88dSmrg      free(arrays);
214af69d88dSmrg      __glXSetError(gc, GL_OUT_OF_MEMORY);
215af69d88dSmrg      return;
216af69d88dSmrg   }
217af69d88dSmrg
218cdc920a0Smrg   arrays->arrays[0].data_type = GL_FLOAT;
219cdc920a0Smrg   arrays->arrays[0].count = 3;
220cdc920a0Smrg   arrays->arrays[0].key = GL_NORMAL_ARRAY;
221cdc920a0Smrg   arrays->arrays[0].normalized = GL_TRUE;
222cdc920a0Smrg   arrays->arrays[0].old_DrawArrays_possible = GL_TRUE;
223cdc920a0Smrg
224cdc920a0Smrg   arrays->arrays[1].data_type = GL_FLOAT;
225cdc920a0Smrg   arrays->arrays[1].count = 4;
226cdc920a0Smrg   arrays->arrays[1].key = GL_COLOR_ARRAY;
227cdc920a0Smrg   arrays->arrays[1].normalized = GL_TRUE;
228cdc920a0Smrg   arrays->arrays[1].old_DrawArrays_possible = GL_TRUE;
229cdc920a0Smrg
230cdc920a0Smrg   arrays->arrays[2].data_type = GL_FLOAT;
231cdc920a0Smrg   arrays->arrays[2].count = 1;
232cdc920a0Smrg   arrays->arrays[2].key = GL_INDEX_ARRAY;
233cdc920a0Smrg   arrays->arrays[2].old_DrawArrays_possible = GL_TRUE;
234cdc920a0Smrg
235cdc920a0Smrg   arrays->arrays[3].data_type = GL_UNSIGNED_BYTE;
236cdc920a0Smrg   arrays->arrays[3].count = 1;
237cdc920a0Smrg   arrays->arrays[3].key = GL_EDGE_FLAG_ARRAY;
238cdc920a0Smrg   arrays->arrays[3].old_DrawArrays_possible = GL_TRUE;
239cdc920a0Smrg
240cdc920a0Smrg   for (i = 0; i < texture_units; i++) {
241cdc920a0Smrg      arrays->arrays[4 + i].data_type = GL_FLOAT;
242cdc920a0Smrg      arrays->arrays[4 + i].count = 4;
243cdc920a0Smrg      arrays->arrays[4 + i].key = GL_TEXTURE_COORD_ARRAY;
244cdc920a0Smrg
245cdc920a0Smrg      arrays->arrays[4 + i].old_DrawArrays_possible = (i == 0);
246cdc920a0Smrg      arrays->arrays[4 + i].index = i;
247cdc920a0Smrg   }
248cdc920a0Smrg
249cdc920a0Smrg   i = 4 + texture_units;
250cdc920a0Smrg
251cdc920a0Smrg   if (got_fog) {
252cdc920a0Smrg      arrays->arrays[i].data_type = GL_FLOAT;
253cdc920a0Smrg      arrays->arrays[i].count = 1;
254cdc920a0Smrg      arrays->arrays[i].key = GL_FOG_COORDINATE_ARRAY;
255cdc920a0Smrg      arrays->arrays[i].old_DrawArrays_possible = GL_TRUE;
256cdc920a0Smrg      i++;
257cdc920a0Smrg   }
258cdc920a0Smrg
259cdc920a0Smrg   if (got_secondary_color) {
260cdc920a0Smrg      arrays->arrays[i].data_type = GL_FLOAT;
261cdc920a0Smrg      arrays->arrays[i].count = 3;
262cdc920a0Smrg      arrays->arrays[i].key = GL_SECONDARY_COLOR_ARRAY;
263cdc920a0Smrg      arrays->arrays[i].old_DrawArrays_possible = GL_TRUE;
264cdc920a0Smrg      arrays->arrays[i].normalized = GL_TRUE;
265cdc920a0Smrg      i++;
266cdc920a0Smrg   }
267cdc920a0Smrg
268cdc920a0Smrg
269cdc920a0Smrg   for (j = 0; j < vertex_program_attribs; j++) {
270cdc920a0Smrg      const unsigned idx = (vertex_program_attribs - (j + 1));
271cdc920a0Smrg
272cdc920a0Smrg
273cdc920a0Smrg      arrays->arrays[idx + i].data_type = GL_FLOAT;
274cdc920a0Smrg      arrays->arrays[idx + i].count = 4;
275cdc920a0Smrg      arrays->arrays[idx + i].key = GL_VERTEX_ATTRIB_ARRAY_POINTER;
276cdc920a0Smrg
277cdc920a0Smrg      arrays->arrays[idx + i].old_DrawArrays_possible = 0;
278cdc920a0Smrg      arrays->arrays[idx + i].index = idx;
279cdc920a0Smrg   }
280cdc920a0Smrg
281cdc920a0Smrg   i += vertex_program_attribs;
282cdc920a0Smrg
283cdc920a0Smrg
28401e04c3fSmrg   /* Vertex array *must* be last because of the way that
285cdc920a0Smrg    * emit_DrawArrays_none works.
286cdc920a0Smrg    */
287cdc920a0Smrg
288cdc920a0Smrg   arrays->arrays[i].data_type = GL_FLOAT;
289cdc920a0Smrg   arrays->arrays[i].count = 4;
290cdc920a0Smrg   arrays->arrays[i].key = GL_VERTEX_ARRAY;
291cdc920a0Smrg   arrays->arrays[i].old_DrawArrays_possible = GL_TRUE;
292cdc920a0Smrg
293cdc920a0Smrg   assert((i + 1) == arrays->num_arrays);
294cdc920a0Smrg
295cdc920a0Smrg   arrays->stack_index = 0;
296cdc920a0Smrg   arrays->stack = malloc(sizeof(struct array_stack_state)
297cdc920a0Smrg                          * arrays->num_arrays
298cdc920a0Smrg                          * __GL_CLIENT_ATTRIB_STACK_DEPTH);
299af69d88dSmrg
300af69d88dSmrg   if (arrays->stack == NULL) {
30101e04c3fSmrg      state->array_state = NULL;
302af69d88dSmrg      free(arrays->arrays);
303af69d88dSmrg      free(arrays);
304af69d88dSmrg      __glXSetError(gc, GL_OUT_OF_MEMORY);
305af69d88dSmrg      return;
306af69d88dSmrg   }
307cdc920a0Smrg}
308cdc920a0Smrg
309cdc920a0Smrg
310cdc920a0Smrg/**
311cdc920a0Smrg * Calculate the size of a single vertex for the "none" protocol.  This is
312cdc920a0Smrg * essentially the size of all the immediate-mode commands required to
313cdc920a0Smrg * implement the enabled vertex arrays.
314cdc920a0Smrg */
315cdc920a0Smrgstatic size_t
316cdc920a0Smrgcalculate_single_vertex_size_none(const struct array_state_vector *arrays)
317cdc920a0Smrg{
318cdc920a0Smrg   size_t single_vertex_size = 0;
319cdc920a0Smrg   unsigned i;
320cdc920a0Smrg
321cdc920a0Smrg
322cdc920a0Smrg   for (i = 0; i < arrays->num_arrays; i++) {
323cdc920a0Smrg      if (arrays->arrays[i].enabled) {
32401e04c3fSmrg         single_vertex_size += arrays->arrays[i].header[0];
325cdc920a0Smrg      }
326cdc920a0Smrg   }
327cdc920a0Smrg
328cdc920a0Smrg   return single_vertex_size;
329cdc920a0Smrg}
330cdc920a0Smrg
331cdc920a0Smrg
332cdc920a0Smrg/**
333cdc920a0Smrg * Emit a single element using non-DrawArrays protocol.
334cdc920a0Smrg */
335cdc920a0SmrgGLubyte *
336cdc920a0Smrgemit_element_none(GLubyte * dst,
337cdc920a0Smrg                  const struct array_state_vector * arrays, unsigned index)
338cdc920a0Smrg{
339cdc920a0Smrg   unsigned i;
340cdc920a0Smrg
341cdc920a0Smrg
342cdc920a0Smrg   for (i = 0; i < arrays->num_arrays; i++) {
343cdc920a0Smrg      if (arrays->arrays[i].enabled) {
344cdc920a0Smrg         const size_t offset = index * arrays->arrays[i].true_stride;
345cdc920a0Smrg
346cdc920a0Smrg         /* The generic attributes can have more data than is in the
347cdc920a0Smrg          * elements.  This is because a vertex array can be a 2 element,
348cdc920a0Smrg          * normalized, unsigned short, but the "closest" immediate mode
349cdc920a0Smrg          * protocol is for a 4Nus.  Since the sizes are small, the
350cdc920a0Smrg          * performance impact on modern processors should be negligible.
351cdc920a0Smrg          */
35201e04c3fSmrg         (void) memset(dst, 0, arrays->arrays[i].header[0]);
35301e04c3fSmrg
35401e04c3fSmrg         (void) memcpy(dst, arrays->arrays[i].header, 4);
35501e04c3fSmrg
35601e04c3fSmrg         dst += 4;
35701e04c3fSmrg
35801e04c3fSmrg         if (arrays->arrays[i].key == GL_TEXTURE_COORD_ARRAY &&
35901e04c3fSmrg             arrays->arrays[i].index > 0) {
36001e04c3fSmrg            /* Multi-texture coordinate arrays require the texture target
36101e04c3fSmrg             * to be sent.  For doubles it is after the data, for everything
36201e04c3fSmrg             * else it is before.
36301e04c3fSmrg             */
36401e04c3fSmrg            GLenum texture = arrays->arrays[i].index + GL_TEXTURE0;
36501e04c3fSmrg            if (arrays->arrays[i].data_type == GL_DOUBLE) {
36601e04c3fSmrg               (void) memcpy(dst, ((GLubyte *) arrays->arrays[i].data) + offset,
36701e04c3fSmrg                             arrays->arrays[i].element_size);
36801e04c3fSmrg               dst += arrays->arrays[i].element_size;
36901e04c3fSmrg               (void) memcpy(dst, &texture, 4);
37001e04c3fSmrg               dst += 4;
37101e04c3fSmrg            } else {
37201e04c3fSmrg               (void) memcpy(dst, &texture, 4);
37301e04c3fSmrg               dst += 4;
37401e04c3fSmrg               (void) memcpy(dst, ((GLubyte *) arrays->arrays[i].data) + offset,
37501e04c3fSmrg                             arrays->arrays[i].element_size);
37601e04c3fSmrg               dst += __GLX_PAD(arrays->arrays[i].element_size);
37701e04c3fSmrg            }
37801e04c3fSmrg         } else if (arrays->arrays[i].key == GL_VERTEX_ATTRIB_ARRAY_POINTER) {
37901e04c3fSmrg            /* Vertex attribute data requires the index sent first.
38001e04c3fSmrg             */
38101e04c3fSmrg            (void) memcpy(dst, &arrays->arrays[i].index, 4);
38201e04c3fSmrg            dst += 4;
38301e04c3fSmrg            (void) memcpy(dst, ((GLubyte *) arrays->arrays[i].data) + offset,
38401e04c3fSmrg                          arrays->arrays[i].element_size);
38501e04c3fSmrg            dst += __GLX_PAD(arrays->arrays[i].element_size);
38601e04c3fSmrg         } else {
38701e04c3fSmrg            (void) memcpy(dst, ((GLubyte *) arrays->arrays[i].data) + offset,
38801e04c3fSmrg                          arrays->arrays[i].element_size);
38901e04c3fSmrg            dst += __GLX_PAD(arrays->arrays[i].element_size);
39001e04c3fSmrg         }
391cdc920a0Smrg      }
392cdc920a0Smrg   }
393cdc920a0Smrg
394cdc920a0Smrg   return dst;
395cdc920a0Smrg}
396cdc920a0Smrg
397cdc920a0Smrg
398cdc920a0Smrg/**
399cdc920a0Smrg * Emit a single element using "old" DrawArrays protocol from
400cdc920a0Smrg * EXT_vertex_arrays / OpenGL 1.1.
401cdc920a0Smrg */
402cdc920a0SmrgGLubyte *
403cdc920a0Smrgemit_element_old(GLubyte * dst,
404cdc920a0Smrg                 const struct array_state_vector * arrays, unsigned index)
405cdc920a0Smrg{
406cdc920a0Smrg   unsigned i;
407cdc920a0Smrg
408cdc920a0Smrg
409cdc920a0Smrg   for (i = 0; i < arrays->num_arrays; i++) {
410cdc920a0Smrg      if (arrays->arrays[i].enabled) {
411cdc920a0Smrg         const size_t offset = index * arrays->arrays[i].true_stride;
412cdc920a0Smrg
413cdc920a0Smrg         (void) memcpy(dst, ((GLubyte *) arrays->arrays[i].data) + offset,
414cdc920a0Smrg                       arrays->arrays[i].element_size);
415cdc920a0Smrg
416cdc920a0Smrg         dst += __GLX_PAD(arrays->arrays[i].element_size);
417cdc920a0Smrg      }
418cdc920a0Smrg   }
419cdc920a0Smrg
420cdc920a0Smrg   return dst;
421cdc920a0Smrg}
422cdc920a0Smrg
423cdc920a0Smrg
424cdc920a0Smrgstruct array_state *
425cdc920a0Smrgget_array_entry(const struct array_state_vector *arrays,
426cdc920a0Smrg                GLenum key, unsigned index)
427cdc920a0Smrg{
428cdc920a0Smrg   unsigned i;
429cdc920a0Smrg
430cdc920a0Smrg   for (i = 0; i < arrays->num_arrays; i++) {
431cdc920a0Smrg      if ((arrays->arrays[i].key == key)
432cdc920a0Smrg          && (arrays->arrays[i].index == index)) {
433cdc920a0Smrg         return &arrays->arrays[i];
434cdc920a0Smrg      }
435cdc920a0Smrg   }
436cdc920a0Smrg
437cdc920a0Smrg   return NULL;
438cdc920a0Smrg}
439cdc920a0Smrg
440cdc920a0Smrg
441cdc920a0Smrgstatic GLboolean
442cdc920a0Smrgallocate_array_info_cache(struct array_state_vector *arrays,
443cdc920a0Smrg                          size_t required_size)
444cdc920a0Smrg{
445cdc920a0Smrg#define MAX_HEADER_SIZE 20
446cdc920a0Smrg   if (arrays->array_info_cache_buffer_size < required_size) {
447cdc920a0Smrg      GLubyte *temp = realloc(arrays->array_info_cache_base,
448cdc920a0Smrg                              required_size + MAX_HEADER_SIZE);
449cdc920a0Smrg
450cdc920a0Smrg      if (temp == NULL) {
451cdc920a0Smrg         return GL_FALSE;
452cdc920a0Smrg      }
453cdc920a0Smrg
454cdc920a0Smrg      arrays->array_info_cache_base = temp;
455cdc920a0Smrg      arrays->array_info_cache = temp + MAX_HEADER_SIZE;
456cdc920a0Smrg      arrays->array_info_cache_buffer_size = required_size;
457cdc920a0Smrg   }
458cdc920a0Smrg
459cdc920a0Smrg   arrays->array_info_cache_size = required_size;
460cdc920a0Smrg   return GL_TRUE;
461cdc920a0Smrg}
462cdc920a0Smrg
463cdc920a0Smrg
464cdc920a0Smrg/**
465cdc920a0Smrg */
466cdc920a0Smrgvoid
467cdc920a0Smrgfill_array_info_cache(struct array_state_vector *arrays)
468cdc920a0Smrg{
469cdc920a0Smrg   GLboolean old_DrawArrays_possible;
470cdc920a0Smrg   unsigned i;
471cdc920a0Smrg
472cdc920a0Smrg
473cdc920a0Smrg   /* Determine how many arrays are enabled.
474cdc920a0Smrg    */
475cdc920a0Smrg
476cdc920a0Smrg   arrays->enabled_client_array_count = 0;
477cdc920a0Smrg   old_DrawArrays_possible = arrays->old_DrawArrays_possible;
478cdc920a0Smrg   for (i = 0; i < arrays->num_arrays; i++) {
479cdc920a0Smrg      if (arrays->arrays[i].enabled) {
480cdc920a0Smrg         arrays->enabled_client_array_count++;
481cdc920a0Smrg         old_DrawArrays_possible &= arrays->arrays[i].old_DrawArrays_possible;
482cdc920a0Smrg      }
483cdc920a0Smrg   }
484cdc920a0Smrg
485cdc920a0Smrg   if (arrays->new_DrawArrays_possible) {
486cdc920a0Smrg      assert(!arrays->new_DrawArrays_possible);
487cdc920a0Smrg   }
488cdc920a0Smrg   else if (old_DrawArrays_possible) {
489cdc920a0Smrg      const size_t required_size = arrays->enabled_client_array_count * 12;
490cdc920a0Smrg      uint32_t *info;
491cdc920a0Smrg
492cdc920a0Smrg
493cdc920a0Smrg      if (!allocate_array_info_cache(arrays, required_size)) {
494cdc920a0Smrg         return;
495cdc920a0Smrg      }
496cdc920a0Smrg
497cdc920a0Smrg
498cdc920a0Smrg      info = (uint32_t *) arrays->array_info_cache;
499cdc920a0Smrg      for (i = 0; i < arrays->num_arrays; i++) {
500cdc920a0Smrg         if (arrays->arrays[i].enabled) {
501cdc920a0Smrg            *(info++) = arrays->arrays[i].data_type;
502cdc920a0Smrg            *(info++) = arrays->arrays[i].count;
503cdc920a0Smrg            *(info++) = arrays->arrays[i].key;
504cdc920a0Smrg         }
505cdc920a0Smrg      }
506cdc920a0Smrg
507cdc920a0Smrg      arrays->DrawArrays = emit_DrawArrays_old;
508cdc920a0Smrg      arrays->DrawElements = emit_DrawElements_old;
509cdc920a0Smrg   }
510cdc920a0Smrg   else {
511cdc920a0Smrg      arrays->DrawArrays = emit_DrawArrays_none;
512cdc920a0Smrg      arrays->DrawElements = emit_DrawElements_none;
513cdc920a0Smrg   }
514cdc920a0Smrg
515cdc920a0Smrg   arrays->array_info_cache_valid = GL_TRUE;
516cdc920a0Smrg}
517cdc920a0Smrg
518cdc920a0Smrg
519cdc920a0Smrg/**
520cdc920a0Smrg * Emit a \c glDrawArrays command using the "none" protocol.  That is,
521cdc920a0Smrg * emit immediate-mode commands that are equivalent to the requiested
522cdc920a0Smrg * \c glDrawArrays command.  This is used with servers that don't support
523cdc920a0Smrg * the OpenGL 1.1 / EXT_vertex_arrays DrawArrays protocol or in cases where
524cdc920a0Smrg * vertex state is enabled that is not compatible with that protocol.
525cdc920a0Smrg */
526cdc920a0Smrgvoid
527cdc920a0Smrgemit_DrawArrays_none(GLenum mode, GLint first, GLsizei count)
528cdc920a0Smrg{
5293464ebd5Sriastradh   struct glx_context *gc = __glXGetCurrentContext();
530cdc920a0Smrg   const __GLXattribute *state =
531cdc920a0Smrg      (const __GLXattribute *) (gc->client_state_private);
532cdc920a0Smrg   struct array_state_vector *arrays = state->array_state;
533cdc920a0Smrg
534cdc920a0Smrg   size_t single_vertex_size;
535cdc920a0Smrg   GLubyte *pc;
536cdc920a0Smrg   unsigned i;
537cdc920a0Smrg   static const uint16_t begin_cmd[2] = { 8, X_GLrop_Begin };
538cdc920a0Smrg   static const uint16_t end_cmd[2] = { 4, X_GLrop_End };
539cdc920a0Smrg
540cdc920a0Smrg
541cdc920a0Smrg   single_vertex_size = calculate_single_vertex_size_none(arrays);
542cdc920a0Smrg
543cdc920a0Smrg   pc = gc->pc;
544cdc920a0Smrg
545cdc920a0Smrg   (void) memcpy(pc, begin_cmd, 4);
546cdc920a0Smrg   *(int *) (pc + 4) = mode;
547cdc920a0Smrg
548cdc920a0Smrg   pc += 8;
549cdc920a0Smrg
550cdc920a0Smrg   for (i = 0; i < count; i++) {
551cdc920a0Smrg      if ((pc + single_vertex_size) >= gc->bufEnd) {
552cdc920a0Smrg         pc = __glXFlushRenderBuffer(gc, pc);
553cdc920a0Smrg      }
554cdc920a0Smrg
555cdc920a0Smrg      pc = emit_element_none(pc, arrays, first + i);
556cdc920a0Smrg   }
557cdc920a0Smrg
558cdc920a0Smrg   if ((pc + 4) >= gc->bufEnd) {
559cdc920a0Smrg      pc = __glXFlushRenderBuffer(gc, pc);
560cdc920a0Smrg   }
561cdc920a0Smrg
562cdc920a0Smrg   (void) memcpy(pc, end_cmd, 4);
563cdc920a0Smrg   pc += 4;
564cdc920a0Smrg
565cdc920a0Smrg   gc->pc = pc;
566cdc920a0Smrg   if (gc->pc > gc->limit) {
567cdc920a0Smrg      (void) __glXFlushRenderBuffer(gc, gc->pc);
568cdc920a0Smrg   }
569cdc920a0Smrg}
570cdc920a0Smrg
571cdc920a0Smrg
572cdc920a0Smrg/**
573cdc920a0Smrg * Emit the header data for the GL 1.1 / EXT_vertex_arrays DrawArrays
574cdc920a0Smrg * protocol.
575cdc920a0Smrg *
576cdc920a0Smrg * \param gc                    GLX context.
577cdc920a0Smrg * \param arrays                Array state.
578cdc920a0Smrg * \param elements_per_request  Location to store the number of elements that
579cdc920a0Smrg *                              can fit in a single Render / RenderLarge
580cdc920a0Smrg *                              command.
581cdc920a0Smrg * \param total_request         Total number of requests for a RenderLarge
582cdc920a0Smrg *                              command.  If a Render command is used, this
583cdc920a0Smrg *                              will be zero.
584cdc920a0Smrg * \param mode                  Drawing mode.
585cdc920a0Smrg * \param count                 Number of vertices.
586cdc920a0Smrg *
587cdc920a0Smrg * \returns
588cdc920a0Smrg * A pointer to the buffer for array data.
589cdc920a0Smrg */
590cdc920a0Smrgstatic GLubyte *
5913464ebd5Sriastradhemit_DrawArrays_header_old(struct glx_context * gc,
592cdc920a0Smrg                           struct array_state_vector *arrays,
593cdc920a0Smrg                           size_t * elements_per_request,
594cdc920a0Smrg                           unsigned int *total_requests,
595cdc920a0Smrg                           GLenum mode, GLsizei count)
596cdc920a0Smrg{
597cdc920a0Smrg   size_t command_size;
598cdc920a0Smrg   size_t single_vertex_size;
599cdc920a0Smrg   const unsigned header_size = 16;
600cdc920a0Smrg   unsigned i;
601cdc920a0Smrg   GLubyte *pc;
602cdc920a0Smrg
603cdc920a0Smrg
604cdc920a0Smrg   /* Determine the size of the whole command.  This includes the header,
605cdc920a0Smrg    * the ARRAY_INFO data and the array data.  Once this size is calculated,
606cdc920a0Smrg    * it will be known whether a Render or RenderLarge command is needed.
607cdc920a0Smrg    */
608cdc920a0Smrg
609cdc920a0Smrg   single_vertex_size = 0;
610cdc920a0Smrg   for (i = 0; i < arrays->num_arrays; i++) {
611cdc920a0Smrg      if (arrays->arrays[i].enabled) {
612cdc920a0Smrg         single_vertex_size += __GLX_PAD(arrays->arrays[i].element_size);
613cdc920a0Smrg      }
614cdc920a0Smrg   }
615cdc920a0Smrg
616cdc920a0Smrg   command_size = arrays->array_info_cache_size + header_size
617cdc920a0Smrg      + (single_vertex_size * count);
618cdc920a0Smrg
619cdc920a0Smrg
620cdc920a0Smrg   /* Write the header for either a Render command or a RenderLarge
621cdc920a0Smrg    * command.  After the header is written, write the ARRAY_INFO data.
622cdc920a0Smrg    */
623cdc920a0Smrg
624cdc920a0Smrg   if (command_size > gc->maxSmallRenderCommandSize) {
625cdc920a0Smrg      /* maxSize is the maximum amount of data can be stuffed into a single
626cdc920a0Smrg       * packet.  sz_xGLXRenderReq is added because bufSize is the maximum
627cdc920a0Smrg       * packet size minus sz_xGLXRenderReq.
628cdc920a0Smrg       */
629cdc920a0Smrg      const size_t maxSize = (gc->bufSize + sz_xGLXRenderReq)
630cdc920a0Smrg         - sz_xGLXRenderLargeReq;
631cdc920a0Smrg      unsigned vertex_requests;
632cdc920a0Smrg
633cdc920a0Smrg
634cdc920a0Smrg      /* Calculate the number of data packets that will be required to send
635cdc920a0Smrg       * the whole command.  To do this, the number of verticies that
636cdc920a0Smrg       * will fit in a single buffer must be calculated.
637cdc920a0Smrg       *
638cdc920a0Smrg       * The important value here is elements_per_request.  This is the
639cdc920a0Smrg       * number of complete array elements that will fit in a single
640cdc920a0Smrg       * buffer.  There may be some wasted space at the end of the buffer,
641cdc920a0Smrg       * but splitting elements across buffer boundries would be painful.
642cdc920a0Smrg       */
643cdc920a0Smrg
644cdc920a0Smrg      elements_per_request[0] = maxSize / single_vertex_size;
645cdc920a0Smrg
646cdc920a0Smrg      vertex_requests = (count + elements_per_request[0] - 1)
647cdc920a0Smrg         / elements_per_request[0];
648cdc920a0Smrg
649cdc920a0Smrg      *total_requests = vertex_requests + 1;
650cdc920a0Smrg
651cdc920a0Smrg
652cdc920a0Smrg      __glXFlushRenderBuffer(gc, gc->pc);
653cdc920a0Smrg
654cdc920a0Smrg      command_size += 4;
655cdc920a0Smrg
656cdc920a0Smrg      pc = ((GLubyte *) arrays->array_info_cache) - (header_size + 4);
657cdc920a0Smrg      *(uint32_t *) (pc + 0) = command_size;
658cdc920a0Smrg      *(uint32_t *) (pc + 4) = X_GLrop_DrawArrays;
659cdc920a0Smrg      *(uint32_t *) (pc + 8) = count;
660cdc920a0Smrg      *(uint32_t *) (pc + 12) = arrays->enabled_client_array_count;
661cdc920a0Smrg      *(uint32_t *) (pc + 16) = mode;
662cdc920a0Smrg
663cdc920a0Smrg      __glXSendLargeChunk(gc, 1, *total_requests, pc,
664cdc920a0Smrg                          header_size + 4 + arrays->array_info_cache_size);
665cdc920a0Smrg
666cdc920a0Smrg      pc = gc->pc;
667cdc920a0Smrg   }
668cdc920a0Smrg   else {
669cdc920a0Smrg      if ((gc->pc + command_size) >= gc->bufEnd) {
670cdc920a0Smrg         (void) __glXFlushRenderBuffer(gc, gc->pc);
671cdc920a0Smrg      }
672cdc920a0Smrg
673cdc920a0Smrg      pc = gc->pc;
674cdc920a0Smrg      *(uint16_t *) (pc + 0) = command_size;
675cdc920a0Smrg      *(uint16_t *) (pc + 2) = X_GLrop_DrawArrays;
676cdc920a0Smrg      *(uint32_t *) (pc + 4) = count;
677cdc920a0Smrg      *(uint32_t *) (pc + 8) = arrays->enabled_client_array_count;
678cdc920a0Smrg      *(uint32_t *) (pc + 12) = mode;
679cdc920a0Smrg
680cdc920a0Smrg      pc += header_size;
681cdc920a0Smrg
682cdc920a0Smrg      (void) memcpy(pc, arrays->array_info_cache,
683cdc920a0Smrg                    arrays->array_info_cache_size);
684cdc920a0Smrg      pc += arrays->array_info_cache_size;
685cdc920a0Smrg
686cdc920a0Smrg      *elements_per_request = count;
687cdc920a0Smrg      *total_requests = 0;
688cdc920a0Smrg   }
689cdc920a0Smrg
690cdc920a0Smrg
691cdc920a0Smrg   return pc;
692cdc920a0Smrg}
693cdc920a0Smrg
694cdc920a0Smrg
695cdc920a0Smrg/**
696cdc920a0Smrg */
697cdc920a0Smrgvoid
698cdc920a0Smrgemit_DrawArrays_old(GLenum mode, GLint first, GLsizei count)
699cdc920a0Smrg{
7003464ebd5Sriastradh   struct glx_context *gc = __glXGetCurrentContext();
701cdc920a0Smrg   const __GLXattribute *state =
702cdc920a0Smrg      (const __GLXattribute *) (gc->client_state_private);
703cdc920a0Smrg   struct array_state_vector *arrays = state->array_state;
704cdc920a0Smrg
705cdc920a0Smrg   GLubyte *pc;
706cdc920a0Smrg   size_t elements_per_request;
707cdc920a0Smrg   unsigned total_requests = 0;
708cdc920a0Smrg   unsigned i;
709cdc920a0Smrg   size_t total_sent = 0;
710cdc920a0Smrg
711cdc920a0Smrg
712cdc920a0Smrg   pc = emit_DrawArrays_header_old(gc, arrays, &elements_per_request,
713cdc920a0Smrg                                   &total_requests, mode, count);
714cdc920a0Smrg
715cdc920a0Smrg
716cdc920a0Smrg   /* Write the arrays.
717cdc920a0Smrg    */
718cdc920a0Smrg
719cdc920a0Smrg   if (total_requests == 0) {
720cdc920a0Smrg      assert(elements_per_request >= count);
721cdc920a0Smrg
722cdc920a0Smrg      for (i = 0; i < count; i++) {
723cdc920a0Smrg         pc = emit_element_old(pc, arrays, i + first);
724cdc920a0Smrg      }
725cdc920a0Smrg
726cdc920a0Smrg      assert(pc <= gc->bufEnd);
727cdc920a0Smrg
728cdc920a0Smrg      gc->pc = pc;
729cdc920a0Smrg      if (gc->pc > gc->limit) {
730cdc920a0Smrg         (void) __glXFlushRenderBuffer(gc, gc->pc);
731cdc920a0Smrg      }
732cdc920a0Smrg   }
733cdc920a0Smrg   else {
734cdc920a0Smrg      unsigned req;
735cdc920a0Smrg
736cdc920a0Smrg
737cdc920a0Smrg      for (req = 2; req <= total_requests; req++) {
738cdc920a0Smrg         if (count < elements_per_request) {
739cdc920a0Smrg            elements_per_request = count;
740cdc920a0Smrg         }
741cdc920a0Smrg
742cdc920a0Smrg         pc = gc->pc;
743cdc920a0Smrg         for (i = 0; i < elements_per_request; i++) {
744cdc920a0Smrg            pc = emit_element_old(pc, arrays, i + first);
745cdc920a0Smrg         }
746cdc920a0Smrg
747cdc920a0Smrg         first += elements_per_request;
748cdc920a0Smrg
749cdc920a0Smrg         total_sent += (size_t) (pc - gc->pc);
750cdc920a0Smrg         __glXSendLargeChunk(gc, req, total_requests, gc->pc, pc - gc->pc);
751cdc920a0Smrg
752cdc920a0Smrg         count -= elements_per_request;
753cdc920a0Smrg      }
754cdc920a0Smrg   }
755cdc920a0Smrg}
756cdc920a0Smrg
757cdc920a0Smrg
758cdc920a0Smrgvoid
759cdc920a0Smrgemit_DrawElements_none(GLenum mode, GLsizei count, GLenum type,
760cdc920a0Smrg                       const GLvoid * indices)
761cdc920a0Smrg{
7623464ebd5Sriastradh   struct glx_context *gc = __glXGetCurrentContext();
763cdc920a0Smrg   const __GLXattribute *state =
764cdc920a0Smrg      (const __GLXattribute *) (gc->client_state_private);
765cdc920a0Smrg   struct array_state_vector *arrays = state->array_state;
766cdc920a0Smrg   static const uint16_t begin_cmd[2] = { 8, X_GLrop_Begin };
767cdc920a0Smrg   static const uint16_t end_cmd[2] = { 4, X_GLrop_End };
768cdc920a0Smrg
769cdc920a0Smrg   GLubyte *pc;
770cdc920a0Smrg   size_t single_vertex_size;
771cdc920a0Smrg   unsigned i;
772cdc920a0Smrg
773cdc920a0Smrg
774cdc920a0Smrg   single_vertex_size = calculate_single_vertex_size_none(arrays);
775cdc920a0Smrg
776cdc920a0Smrg
777cdc920a0Smrg   if ((gc->pc + single_vertex_size) >= gc->bufEnd) {
778cdc920a0Smrg      gc->pc = __glXFlushRenderBuffer(gc, gc->pc);
779cdc920a0Smrg   }
780cdc920a0Smrg
781cdc920a0Smrg   pc = gc->pc;
782cdc920a0Smrg
783cdc920a0Smrg   (void) memcpy(pc, begin_cmd, 4);
784cdc920a0Smrg   *(int *) (pc + 4) = mode;
785cdc920a0Smrg
786cdc920a0Smrg   pc += 8;
787cdc920a0Smrg
788cdc920a0Smrg   for (i = 0; i < count; i++) {
789cdc920a0Smrg      unsigned index = 0;
790cdc920a0Smrg
791cdc920a0Smrg      if ((pc + single_vertex_size) >= gc->bufEnd) {
792cdc920a0Smrg         pc = __glXFlushRenderBuffer(gc, pc);
793cdc920a0Smrg      }
794cdc920a0Smrg
795cdc920a0Smrg      switch (type) {
796cdc920a0Smrg      case GL_UNSIGNED_INT:
797cdc920a0Smrg         index = (unsigned) (((GLuint *) indices)[i]);
798cdc920a0Smrg         break;
799cdc920a0Smrg      case GL_UNSIGNED_SHORT:
800cdc920a0Smrg         index = (unsigned) (((GLushort *) indices)[i]);
801cdc920a0Smrg         break;
802cdc920a0Smrg      case GL_UNSIGNED_BYTE:
803cdc920a0Smrg         index = (unsigned) (((GLubyte *) indices)[i]);
804cdc920a0Smrg         break;
805cdc920a0Smrg      }
806cdc920a0Smrg      pc = emit_element_none(pc, arrays, index);
807cdc920a0Smrg   }
808cdc920a0Smrg
809cdc920a0Smrg   if ((pc + 4) >= gc->bufEnd) {
810cdc920a0Smrg      pc = __glXFlushRenderBuffer(gc, pc);
811cdc920a0Smrg   }
812cdc920a0Smrg
813cdc920a0Smrg   (void) memcpy(pc, end_cmd, 4);
814cdc920a0Smrg   pc += 4;
815cdc920a0Smrg
816cdc920a0Smrg   gc->pc = pc;
817cdc920a0Smrg   if (gc->pc > gc->limit) {
818cdc920a0Smrg      (void) __glXFlushRenderBuffer(gc, gc->pc);
819cdc920a0Smrg   }
820cdc920a0Smrg}
821cdc920a0Smrg
822cdc920a0Smrg
823cdc920a0Smrg/**
824cdc920a0Smrg */
825cdc920a0Smrgvoid
826cdc920a0Smrgemit_DrawElements_old(GLenum mode, GLsizei count, GLenum type,
827cdc920a0Smrg                      const GLvoid * indices)
828cdc920a0Smrg{
8293464ebd5Sriastradh   struct glx_context *gc = __glXGetCurrentContext();
830cdc920a0Smrg   const __GLXattribute *state =
831cdc920a0Smrg      (const __GLXattribute *) (gc->client_state_private);
832cdc920a0Smrg   struct array_state_vector *arrays = state->array_state;
833cdc920a0Smrg
834cdc920a0Smrg   GLubyte *pc;
835cdc920a0Smrg   size_t elements_per_request;
836cdc920a0Smrg   unsigned total_requests = 0;
837cdc920a0Smrg   unsigned i;
838cdc920a0Smrg   unsigned req;
839cdc920a0Smrg   unsigned req_element = 0;
840cdc920a0Smrg
841cdc920a0Smrg
842cdc920a0Smrg   pc = emit_DrawArrays_header_old(gc, arrays, &elements_per_request,
843cdc920a0Smrg                                   &total_requests, mode, count);
844cdc920a0Smrg
845cdc920a0Smrg
846cdc920a0Smrg   /* Write the arrays.
847cdc920a0Smrg    */
848cdc920a0Smrg
849cdc920a0Smrg   req = 2;
850cdc920a0Smrg   while (count > 0) {
851cdc920a0Smrg      if (count < elements_per_request) {
852cdc920a0Smrg         elements_per_request = count;
853cdc920a0Smrg      }
854cdc920a0Smrg
855cdc920a0Smrg      switch (type) {
856cdc920a0Smrg      case GL_UNSIGNED_INT:{
857cdc920a0Smrg            const GLuint *ui_ptr = (const GLuint *) indices + req_element;
858cdc920a0Smrg
859cdc920a0Smrg            for (i = 0; i < elements_per_request; i++) {
860cdc920a0Smrg               const GLint index = (GLint) * (ui_ptr++);
861cdc920a0Smrg               pc = emit_element_old(pc, arrays, index);
862cdc920a0Smrg            }
863cdc920a0Smrg            break;
864cdc920a0Smrg         }
865cdc920a0Smrg      case GL_UNSIGNED_SHORT:{
866cdc920a0Smrg            const GLushort *us_ptr = (const GLushort *) indices + req_element;
867cdc920a0Smrg
868cdc920a0Smrg            for (i = 0; i < elements_per_request; i++) {
869cdc920a0Smrg               const GLint index = (GLint) * (us_ptr++);
870cdc920a0Smrg               pc = emit_element_old(pc, arrays, index);
871cdc920a0Smrg            }
872cdc920a0Smrg            break;
873cdc920a0Smrg         }
874cdc920a0Smrg      case GL_UNSIGNED_BYTE:{
875cdc920a0Smrg            const GLubyte *ub_ptr = (const GLubyte *) indices + req_element;
876cdc920a0Smrg
877cdc920a0Smrg            for (i = 0; i < elements_per_request; i++) {
878cdc920a0Smrg               const GLint index = (GLint) * (ub_ptr++);
879cdc920a0Smrg               pc = emit_element_old(pc, arrays, index);
880cdc920a0Smrg            }
881cdc920a0Smrg            break;
882cdc920a0Smrg         }
883cdc920a0Smrg      }
884cdc920a0Smrg
885cdc920a0Smrg      if (total_requests != 0) {
886cdc920a0Smrg         __glXSendLargeChunk(gc, req, total_requests, gc->pc, pc - gc->pc);
887cdc920a0Smrg         pc = gc->pc;
888cdc920a0Smrg         req++;
889cdc920a0Smrg      }
890cdc920a0Smrg
891cdc920a0Smrg      count -= elements_per_request;
892cdc920a0Smrg      req_element += elements_per_request;
893cdc920a0Smrg   }
894cdc920a0Smrg
895cdc920a0Smrg
896cdc920a0Smrg   assert((total_requests == 0) || ((req - 1) == total_requests));
897cdc920a0Smrg
898cdc920a0Smrg   if (total_requests == 0) {
899cdc920a0Smrg      assert(pc <= gc->bufEnd);
900cdc920a0Smrg
901cdc920a0Smrg      gc->pc = pc;
902cdc920a0Smrg      if (gc->pc > gc->limit) {
903cdc920a0Smrg         (void) __glXFlushRenderBuffer(gc, gc->pc);
904cdc920a0Smrg      }
905cdc920a0Smrg   }
906cdc920a0Smrg}
907cdc920a0Smrg
908cdc920a0Smrg
909cdc920a0Smrg/**
910cdc920a0Smrg * Validate that the \c mode parameter to \c glDrawArrays, et. al. is valid.
911cdc920a0Smrg * If it is not valid, then an error code is set in the GLX context.
912cdc920a0Smrg *
913cdc920a0Smrg * \returns
914cdc920a0Smrg * \c GL_TRUE if the argument is valid, \c GL_FALSE if is not.
915cdc920a0Smrg */
916cdc920a0Smrgstatic GLboolean
9173464ebd5Sriastradhvalidate_mode(struct glx_context * gc, GLenum mode)
918cdc920a0Smrg{
919cdc920a0Smrg   switch (mode) {
920cdc920a0Smrg   case GL_POINTS:
921cdc920a0Smrg   case GL_LINE_STRIP:
922cdc920a0Smrg   case GL_LINE_LOOP:
923cdc920a0Smrg   case GL_LINES:
924cdc920a0Smrg   case GL_TRIANGLE_STRIP:
925cdc920a0Smrg   case GL_TRIANGLE_FAN:
926cdc920a0Smrg   case GL_TRIANGLES:
927cdc920a0Smrg   case GL_QUAD_STRIP:
928cdc920a0Smrg   case GL_QUADS:
929cdc920a0Smrg   case GL_POLYGON:
930cdc920a0Smrg      break;
931cdc920a0Smrg   default:
932cdc920a0Smrg      __glXSetError(gc, GL_INVALID_ENUM);
933cdc920a0Smrg      return GL_FALSE;
934cdc920a0Smrg   }
935cdc920a0Smrg
936cdc920a0Smrg   return GL_TRUE;
937cdc920a0Smrg}
938cdc920a0Smrg
939cdc920a0Smrg
940cdc920a0Smrg/**
941cdc920a0Smrg * Validate that the \c count parameter to \c glDrawArrays, et. al. is valid.
942cdc920a0Smrg * A value less than zero is invalid and will result in \c GL_INVALID_VALUE
943cdc920a0Smrg * being set.  A value of zero will not result in an error being set, but
944cdc920a0Smrg * will result in \c GL_FALSE being returned.
945cdc920a0Smrg *
946cdc920a0Smrg * \returns
947cdc920a0Smrg * \c GL_TRUE if the argument is valid, \c GL_FALSE if it is not.
948cdc920a0Smrg */
949cdc920a0Smrgstatic GLboolean
9503464ebd5Sriastradhvalidate_count(struct glx_context * gc, GLsizei count)
951cdc920a0Smrg{
952cdc920a0Smrg   if (count < 0) {
953cdc920a0Smrg      __glXSetError(gc, GL_INVALID_VALUE);
954cdc920a0Smrg   }
955cdc920a0Smrg
956cdc920a0Smrg   return (count > 0);
957cdc920a0Smrg}
958cdc920a0Smrg
959cdc920a0Smrg
960cdc920a0Smrg/**
961cdc920a0Smrg * Validate that the \c type parameter to \c glDrawElements, et. al. is
962cdc920a0Smrg * valid.  Only \c GL_UNSIGNED_BYTE, \c GL_UNSIGNED_SHORT, and
963cdc920a0Smrg * \c GL_UNSIGNED_INT are valid.
964cdc920a0Smrg *
965cdc920a0Smrg * \returns
966cdc920a0Smrg * \c GL_TRUE if the argument is valid, \c GL_FALSE if it is not.
967cdc920a0Smrg */
968cdc920a0Smrgstatic GLboolean
9693464ebd5Sriastradhvalidate_type(struct glx_context * gc, GLenum type)
970cdc920a0Smrg{
971cdc920a0Smrg   switch (type) {
972cdc920a0Smrg   case GL_UNSIGNED_INT:
973cdc920a0Smrg   case GL_UNSIGNED_SHORT:
974cdc920a0Smrg   case GL_UNSIGNED_BYTE:
975cdc920a0Smrg      return GL_TRUE;
976cdc920a0Smrg   default:
977cdc920a0Smrg      __glXSetError(gc, GL_INVALID_ENUM);
978cdc920a0Smrg      return GL_FALSE;
979cdc920a0Smrg   }
980cdc920a0Smrg}
981cdc920a0Smrg
982cdc920a0Smrg
983cdc920a0Smrgvoid
984cdc920a0Smrg__indirect_glDrawArrays(GLenum mode, GLint first, GLsizei count)
985cdc920a0Smrg{
9863464ebd5Sriastradh   struct glx_context *gc = __glXGetCurrentContext();
987cdc920a0Smrg   const __GLXattribute *state =
988cdc920a0Smrg      (const __GLXattribute *) (gc->client_state_private);
989cdc920a0Smrg   struct array_state_vector *arrays = state->array_state;
990cdc920a0Smrg
991cdc920a0Smrg
992cdc920a0Smrg   if (validate_mode(gc, mode) && validate_count(gc, count)) {
993cdc920a0Smrg      if (!arrays->array_info_cache_valid) {
994cdc920a0Smrg         fill_array_info_cache(arrays);
995cdc920a0Smrg      }
996cdc920a0Smrg
997cdc920a0Smrg      arrays->DrawArrays(mode, first, count);
998cdc920a0Smrg   }
999cdc920a0Smrg}
1000cdc920a0Smrg
1001cdc920a0Smrg
1002cdc920a0Smrgvoid
1003cdc920a0Smrg__indirect_glArrayElement(GLint index)
1004cdc920a0Smrg{
10053464ebd5Sriastradh   struct glx_context *gc = __glXGetCurrentContext();
1006cdc920a0Smrg   const __GLXattribute *state =
1007cdc920a0Smrg      (const __GLXattribute *) (gc->client_state_private);
1008cdc920a0Smrg   struct array_state_vector *arrays = state->array_state;
1009cdc920a0Smrg
1010cdc920a0Smrg   size_t single_vertex_size;
1011cdc920a0Smrg
1012cdc920a0Smrg
1013cdc920a0Smrg   single_vertex_size = calculate_single_vertex_size_none(arrays);
1014cdc920a0Smrg
1015cdc920a0Smrg   if ((gc->pc + single_vertex_size) >= gc->bufEnd) {
1016cdc920a0Smrg      gc->pc = __glXFlushRenderBuffer(gc, gc->pc);
1017cdc920a0Smrg   }
1018cdc920a0Smrg
1019cdc920a0Smrg   gc->pc = emit_element_none(gc->pc, arrays, index);
1020cdc920a0Smrg
1021cdc920a0Smrg   if (gc->pc > gc->limit) {
1022cdc920a0Smrg      (void) __glXFlushRenderBuffer(gc, gc->pc);
1023cdc920a0Smrg   }
1024cdc920a0Smrg}
1025cdc920a0Smrg
1026cdc920a0Smrg
1027cdc920a0Smrgvoid
1028cdc920a0Smrg__indirect_glDrawElements(GLenum mode, GLsizei count, GLenum type,
1029cdc920a0Smrg                          const GLvoid * indices)
1030cdc920a0Smrg{
10313464ebd5Sriastradh   struct glx_context *gc = __glXGetCurrentContext();
1032cdc920a0Smrg   const __GLXattribute *state =
1033cdc920a0Smrg      (const __GLXattribute *) (gc->client_state_private);
1034cdc920a0Smrg   struct array_state_vector *arrays = state->array_state;
1035cdc920a0Smrg
1036cdc920a0Smrg
1037cdc920a0Smrg   if (validate_mode(gc, mode) && validate_count(gc, count)
1038cdc920a0Smrg       && validate_type(gc, type)) {
1039cdc920a0Smrg      if (!arrays->array_info_cache_valid) {
1040cdc920a0Smrg         fill_array_info_cache(arrays);
1041cdc920a0Smrg      }
1042cdc920a0Smrg
1043cdc920a0Smrg      arrays->DrawElements(mode, count, type, indices);
1044cdc920a0Smrg   }
1045cdc920a0Smrg}
1046cdc920a0Smrg
1047cdc920a0Smrg
1048cdc920a0Smrgvoid
1049cdc920a0Smrg__indirect_glDrawRangeElements(GLenum mode, GLuint start, GLuint end,
1050cdc920a0Smrg                               GLsizei count, GLenum type,
1051cdc920a0Smrg                               const GLvoid * indices)
1052cdc920a0Smrg{
10533464ebd5Sriastradh   struct glx_context *gc = __glXGetCurrentContext();
1054cdc920a0Smrg   const __GLXattribute *state =
1055cdc920a0Smrg      (const __GLXattribute *) (gc->client_state_private);
1056cdc920a0Smrg   struct array_state_vector *arrays = state->array_state;
1057cdc920a0Smrg
1058cdc920a0Smrg
1059cdc920a0Smrg   if (validate_mode(gc, mode) && validate_count(gc, count)
1060cdc920a0Smrg       && validate_type(gc, type)) {
1061cdc920a0Smrg      if (end < start) {
1062cdc920a0Smrg         __glXSetError(gc, GL_INVALID_VALUE);
1063cdc920a0Smrg         return;
1064cdc920a0Smrg      }
1065cdc920a0Smrg
1066cdc920a0Smrg      if (!arrays->array_info_cache_valid) {
1067cdc920a0Smrg         fill_array_info_cache(arrays);
1068cdc920a0Smrg      }
1069cdc920a0Smrg
1070cdc920a0Smrg      arrays->DrawElements(mode, count, type, indices);
1071cdc920a0Smrg   }
1072cdc920a0Smrg}
1073cdc920a0Smrg
1074cdc920a0Smrg
1075cdc920a0Smrgvoid
1076af69d88dSmrg__indirect_glMultiDrawArrays(GLenum mode, const GLint *first,
10773464ebd5Sriastradh                                const GLsizei *count, GLsizei primcount)
1078cdc920a0Smrg{
10793464ebd5Sriastradh   struct glx_context *gc = __glXGetCurrentContext();
1080cdc920a0Smrg   const __GLXattribute *state =
1081cdc920a0Smrg      (const __GLXattribute *) (gc->client_state_private);
1082cdc920a0Smrg   struct array_state_vector *arrays = state->array_state;
1083cdc920a0Smrg   GLsizei i;
1084cdc920a0Smrg
1085cdc920a0Smrg
1086cdc920a0Smrg   if (validate_mode(gc, mode)) {
1087cdc920a0Smrg      if (!arrays->array_info_cache_valid) {
1088cdc920a0Smrg         fill_array_info_cache(arrays);
1089cdc920a0Smrg      }
1090cdc920a0Smrg
1091cdc920a0Smrg      for (i = 0; i < primcount; i++) {
1092cdc920a0Smrg         if (validate_count(gc, count[i])) {
1093cdc920a0Smrg            arrays->DrawArrays(mode, first[i], count[i]);
1094cdc920a0Smrg         }
1095cdc920a0Smrg      }
1096cdc920a0Smrg   }
1097cdc920a0Smrg}
1098cdc920a0Smrg
1099cdc920a0Smrg
1100cdc920a0Smrgvoid
1101cdc920a0Smrg__indirect_glMultiDrawElementsEXT(GLenum mode, const GLsizei * count,
1102af69d88dSmrg                                  GLenum type, const GLvoid * const * indices,
1103cdc920a0Smrg                                  GLsizei primcount)
1104cdc920a0Smrg{
11053464ebd5Sriastradh   struct glx_context *gc = __glXGetCurrentContext();
1106cdc920a0Smrg   const __GLXattribute *state =
1107cdc920a0Smrg      (const __GLXattribute *) (gc->client_state_private);
1108cdc920a0Smrg   struct array_state_vector *arrays = state->array_state;
1109cdc920a0Smrg   GLsizei i;
1110cdc920a0Smrg
1111cdc920a0Smrg
1112cdc920a0Smrg   if (validate_mode(gc, mode) && validate_type(gc, type)) {
1113cdc920a0Smrg      if (!arrays->array_info_cache_valid) {
1114cdc920a0Smrg         fill_array_info_cache(arrays);
1115cdc920a0Smrg      }
1116cdc920a0Smrg
1117cdc920a0Smrg      for (i = 0; i < primcount; i++) {
1118cdc920a0Smrg         if (validate_count(gc, count[i])) {
1119cdc920a0Smrg            arrays->DrawElements(mode, count[i], type, indices[i]);
1120cdc920a0Smrg         }
1121cdc920a0Smrg      }
1122cdc920a0Smrg   }
1123cdc920a0Smrg}
1124cdc920a0Smrg
1125cdc920a0Smrg
112601e04c3fSmrg/* The HDR_SIZE macro argument is the command header size (4 bytes)
112701e04c3fSmrg * plus any additional index word e.g. for texture units or vertex
112801e04c3fSmrg * attributes.
112901e04c3fSmrg */
1130cdc920a0Smrg#define COMMON_ARRAY_DATA_INIT(a, PTR, TYPE, STRIDE, COUNT, NORMALIZED, HDR_SIZE, OPCODE) \
1131cdc920a0Smrg  do {                                                                  \
1132cdc920a0Smrg    (a)->data = PTR;                                                    \
1133cdc920a0Smrg    (a)->data_type = TYPE;                                              \
1134cdc920a0Smrg    (a)->user_stride = STRIDE;                                          \
1135cdc920a0Smrg    (a)->count = COUNT;                                                 \
1136cdc920a0Smrg    (a)->normalized = NORMALIZED;                                       \
1137cdc920a0Smrg                                                                        \
1138cdc920a0Smrg    (a)->element_size = __glXTypeSize( TYPE ) * COUNT;                  \
1139cdc920a0Smrg    (a)->true_stride = (STRIDE == 0)                                    \
1140cdc920a0Smrg      ? (a)->element_size : STRIDE;                                     \
1141cdc920a0Smrg                                                                        \
114201e04c3fSmrg    (a)->header[0] = __GLX_PAD(HDR_SIZE + (a)->element_size);           \
114301e04c3fSmrg    (a)->header[1] = OPCODE;                                            \
1144cdc920a0Smrg  } while(0)
1145cdc920a0Smrg
1146cdc920a0Smrg
1147cdc920a0Smrgvoid
1148cdc920a0Smrg__indirect_glVertexPointer(GLint size, GLenum type, GLsizei stride,
1149cdc920a0Smrg                           const GLvoid * pointer)
1150cdc920a0Smrg{
1151cdc920a0Smrg   static const uint16_t short_ops[5] = {
1152cdc920a0Smrg      0, 0, X_GLrop_Vertex2sv, X_GLrop_Vertex3sv, X_GLrop_Vertex4sv
1153cdc920a0Smrg   };
1154cdc920a0Smrg   static const uint16_t int_ops[5] = {
1155cdc920a0Smrg      0, 0, X_GLrop_Vertex2iv, X_GLrop_Vertex3iv, X_GLrop_Vertex4iv
1156cdc920a0Smrg   };
1157cdc920a0Smrg   static const uint16_t float_ops[5] = {
1158cdc920a0Smrg      0, 0, X_GLrop_Vertex2fv, X_GLrop_Vertex3fv, X_GLrop_Vertex4fv
1159cdc920a0Smrg   };
1160cdc920a0Smrg   static const uint16_t double_ops[5] = {
1161cdc920a0Smrg      0, 0, X_GLrop_Vertex2dv, X_GLrop_Vertex3dv, X_GLrop_Vertex4dv
1162cdc920a0Smrg   };
1163cdc920a0Smrg   uint16_t opcode;
11643464ebd5Sriastradh   struct glx_context *gc = __glXGetCurrentContext();
1165cdc920a0Smrg   __GLXattribute *state = (__GLXattribute *) (gc->client_state_private);
1166cdc920a0Smrg   struct array_state_vector *arrays = state->array_state;
1167cdc920a0Smrg   struct array_state *a;
1168cdc920a0Smrg
1169cdc920a0Smrg
1170cdc920a0Smrg   if (size < 2 || size > 4 || stride < 0) {
1171cdc920a0Smrg      __glXSetError(gc, GL_INVALID_VALUE);
1172cdc920a0Smrg      return;
1173cdc920a0Smrg   }
1174cdc920a0Smrg
1175cdc920a0Smrg   switch (type) {
1176cdc920a0Smrg   case GL_SHORT:
1177cdc920a0Smrg      opcode = short_ops[size];
1178cdc920a0Smrg      break;
1179cdc920a0Smrg   case GL_INT:
1180cdc920a0Smrg      opcode = int_ops[size];
1181cdc920a0Smrg      break;
1182cdc920a0Smrg   case GL_FLOAT:
1183cdc920a0Smrg      opcode = float_ops[size];
1184cdc920a0Smrg      break;
1185cdc920a0Smrg   case GL_DOUBLE:
1186cdc920a0Smrg      opcode = double_ops[size];
1187cdc920a0Smrg      break;
1188cdc920a0Smrg   default:
1189cdc920a0Smrg      __glXSetError(gc, GL_INVALID_ENUM);
1190cdc920a0Smrg      return;
1191cdc920a0Smrg   }
1192cdc920a0Smrg
1193cdc920a0Smrg   a = get_array_entry(arrays, GL_VERTEX_ARRAY, 0);
1194cdc920a0Smrg   assert(a != NULL);
1195cdc920a0Smrg   COMMON_ARRAY_DATA_INIT(a, pointer, type, stride, size, GL_FALSE, 4,
1196cdc920a0Smrg                          opcode);
1197cdc920a0Smrg
1198cdc920a0Smrg   if (a->enabled) {
1199cdc920a0Smrg      arrays->array_info_cache_valid = GL_FALSE;
1200cdc920a0Smrg   }
1201cdc920a0Smrg}
1202cdc920a0Smrg
1203cdc920a0Smrg
1204cdc920a0Smrgvoid
1205cdc920a0Smrg__indirect_glNormalPointer(GLenum type, GLsizei stride,
1206cdc920a0Smrg                           const GLvoid * pointer)
1207cdc920a0Smrg{
1208cdc920a0Smrg   uint16_t opcode;
12093464ebd5Sriastradh   struct glx_context *gc = __glXGetCurrentContext();
1210cdc920a0Smrg   __GLXattribute *state = (__GLXattribute *) (gc->client_state_private);
1211cdc920a0Smrg   struct array_state_vector *arrays = state->array_state;
1212cdc920a0Smrg   struct array_state *a;
1213cdc920a0Smrg
1214cdc920a0Smrg
1215cdc920a0Smrg   if (stride < 0) {
1216cdc920a0Smrg      __glXSetError(gc, GL_INVALID_VALUE);
1217cdc920a0Smrg      return;
1218cdc920a0Smrg   }
1219cdc920a0Smrg
1220cdc920a0Smrg   switch (type) {
1221cdc920a0Smrg   case GL_BYTE:
1222cdc920a0Smrg      opcode = X_GLrop_Normal3bv;
1223cdc920a0Smrg      break;
1224cdc920a0Smrg   case GL_SHORT:
1225cdc920a0Smrg      opcode = X_GLrop_Normal3sv;
1226cdc920a0Smrg      break;
1227cdc920a0Smrg   case GL_INT:
1228cdc920a0Smrg      opcode = X_GLrop_Normal3iv;
1229cdc920a0Smrg      break;
1230cdc920a0Smrg   case GL_FLOAT:
1231cdc920a0Smrg      opcode = X_GLrop_Normal3fv;
1232cdc920a0Smrg      break;
1233cdc920a0Smrg   case GL_DOUBLE:
1234cdc920a0Smrg      opcode = X_GLrop_Normal3dv;
1235cdc920a0Smrg      break;
1236cdc920a0Smrg   default:
1237cdc920a0Smrg      __glXSetError(gc, GL_INVALID_ENUM);
1238cdc920a0Smrg      return;
1239cdc920a0Smrg   }
1240cdc920a0Smrg
1241cdc920a0Smrg   a = get_array_entry(arrays, GL_NORMAL_ARRAY, 0);
1242cdc920a0Smrg   assert(a != NULL);
1243cdc920a0Smrg   COMMON_ARRAY_DATA_INIT(a, pointer, type, stride, 3, GL_TRUE, 4, opcode);
1244cdc920a0Smrg
1245cdc920a0Smrg   if (a->enabled) {
1246cdc920a0Smrg      arrays->array_info_cache_valid = GL_FALSE;
1247cdc920a0Smrg   }
1248cdc920a0Smrg}
1249cdc920a0Smrg
1250cdc920a0Smrg
1251cdc920a0Smrgvoid
1252cdc920a0Smrg__indirect_glColorPointer(GLint size, GLenum type, GLsizei stride,
1253cdc920a0Smrg                          const GLvoid * pointer)
1254cdc920a0Smrg{
1255cdc920a0Smrg   static const uint16_t byte_ops[5] = {
1256cdc920a0Smrg      0, 0, 0, X_GLrop_Color3bv, X_GLrop_Color4bv
1257cdc920a0Smrg   };
1258cdc920a0Smrg   static const uint16_t ubyte_ops[5] = {
1259cdc920a0Smrg      0, 0, 0, X_GLrop_Color3ubv, X_GLrop_Color4ubv
1260cdc920a0Smrg   };
1261cdc920a0Smrg   static const uint16_t short_ops[5] = {
1262cdc920a0Smrg      0, 0, 0, X_GLrop_Color3sv, X_GLrop_Color4sv
1263cdc920a0Smrg   };
1264cdc920a0Smrg   static const uint16_t ushort_ops[5] = {
1265cdc920a0Smrg      0, 0, 0, X_GLrop_Color3usv, X_GLrop_Color4usv
1266cdc920a0Smrg   };
1267cdc920a0Smrg   static const uint16_t int_ops[5] = {
1268cdc920a0Smrg      0, 0, 0, X_GLrop_Color3iv, X_GLrop_Color4iv
1269cdc920a0Smrg   };
1270cdc920a0Smrg   static const uint16_t uint_ops[5] = {
1271cdc920a0Smrg      0, 0, 0, X_GLrop_Color3uiv, X_GLrop_Color4uiv
1272cdc920a0Smrg   };
1273cdc920a0Smrg   static const uint16_t float_ops[5] = {
1274cdc920a0Smrg      0, 0, 0, X_GLrop_Color3fv, X_GLrop_Color4fv
1275cdc920a0Smrg   };
1276cdc920a0Smrg   static const uint16_t double_ops[5] = {
1277cdc920a0Smrg      0, 0, 0, X_GLrop_Color3dv, X_GLrop_Color4dv
1278cdc920a0Smrg   };
1279cdc920a0Smrg   uint16_t opcode;
12803464ebd5Sriastradh   struct glx_context *gc = __glXGetCurrentContext();
1281cdc920a0Smrg   __GLXattribute *state = (__GLXattribute *) (gc->client_state_private);
1282cdc920a0Smrg   struct array_state_vector *arrays = state->array_state;
1283cdc920a0Smrg   struct array_state *a;
1284cdc920a0Smrg
1285cdc920a0Smrg
1286cdc920a0Smrg   if (size < 3 || size > 4 || stride < 0) {
1287cdc920a0Smrg      __glXSetError(gc, GL_INVALID_VALUE);
1288cdc920a0Smrg      return;
1289cdc920a0Smrg   }
1290cdc920a0Smrg
1291cdc920a0Smrg   switch (type) {
1292cdc920a0Smrg   case GL_BYTE:
1293cdc920a0Smrg      opcode = byte_ops[size];
1294cdc920a0Smrg      break;
1295cdc920a0Smrg   case GL_UNSIGNED_BYTE:
1296cdc920a0Smrg      opcode = ubyte_ops[size];
1297cdc920a0Smrg      break;
1298cdc920a0Smrg   case GL_SHORT:
1299cdc920a0Smrg      opcode = short_ops[size];
1300cdc920a0Smrg      break;
1301cdc920a0Smrg   case GL_UNSIGNED_SHORT:
1302cdc920a0Smrg      opcode = ushort_ops[size];
1303cdc920a0Smrg      break;
1304cdc920a0Smrg   case GL_INT:
1305cdc920a0Smrg      opcode = int_ops[size];
1306cdc920a0Smrg      break;
1307cdc920a0Smrg   case GL_UNSIGNED_INT:
1308cdc920a0Smrg      opcode = uint_ops[size];
1309cdc920a0Smrg      break;
1310cdc920a0Smrg   case GL_FLOAT:
1311cdc920a0Smrg      opcode = float_ops[size];
1312cdc920a0Smrg      break;
1313cdc920a0Smrg   case GL_DOUBLE:
1314cdc920a0Smrg      opcode = double_ops[size];
1315cdc920a0Smrg      break;
1316cdc920a0Smrg   default:
1317cdc920a0Smrg      __glXSetError(gc, GL_INVALID_ENUM);
1318cdc920a0Smrg      return;
1319cdc920a0Smrg   }
1320cdc920a0Smrg
1321cdc920a0Smrg   a = get_array_entry(arrays, GL_COLOR_ARRAY, 0);
1322cdc920a0Smrg   assert(a != NULL);
1323cdc920a0Smrg   COMMON_ARRAY_DATA_INIT(a, pointer, type, stride, size, GL_TRUE, 4, opcode);
1324cdc920a0Smrg
1325cdc920a0Smrg   if (a->enabled) {
1326cdc920a0Smrg      arrays->array_info_cache_valid = GL_FALSE;
1327cdc920a0Smrg   }
1328cdc920a0Smrg}
1329cdc920a0Smrg
1330cdc920a0Smrg
1331cdc920a0Smrgvoid
1332cdc920a0Smrg__indirect_glIndexPointer(GLenum type, GLsizei stride, const GLvoid * pointer)
1333cdc920a0Smrg{
1334cdc920a0Smrg   uint16_t opcode;
13353464ebd5Sriastradh   struct glx_context *gc = __glXGetCurrentContext();
1336cdc920a0Smrg   __GLXattribute *state = (__GLXattribute *) (gc->client_state_private);
1337cdc920a0Smrg   struct array_state_vector *arrays = state->array_state;
1338cdc920a0Smrg   struct array_state *a;
1339cdc920a0Smrg
1340cdc920a0Smrg
1341cdc920a0Smrg   if (stride < 0) {
1342cdc920a0Smrg      __glXSetError(gc, GL_INVALID_VALUE);
1343cdc920a0Smrg      return;
1344cdc920a0Smrg   }
1345cdc920a0Smrg
1346cdc920a0Smrg   switch (type) {
1347cdc920a0Smrg   case GL_UNSIGNED_BYTE:
1348cdc920a0Smrg      opcode = X_GLrop_Indexubv;
1349cdc920a0Smrg      break;
1350cdc920a0Smrg   case GL_SHORT:
1351cdc920a0Smrg      opcode = X_GLrop_Indexsv;
1352cdc920a0Smrg      break;
1353cdc920a0Smrg   case GL_INT:
1354cdc920a0Smrg      opcode = X_GLrop_Indexiv;
1355cdc920a0Smrg      break;
1356cdc920a0Smrg   case GL_FLOAT:
1357cdc920a0Smrg      opcode = X_GLrop_Indexfv;
1358cdc920a0Smrg      break;
1359cdc920a0Smrg   case GL_DOUBLE:
1360cdc920a0Smrg      opcode = X_GLrop_Indexdv;
1361cdc920a0Smrg      break;
1362cdc920a0Smrg   default:
1363cdc920a0Smrg      __glXSetError(gc, GL_INVALID_ENUM);
1364cdc920a0Smrg      return;
1365cdc920a0Smrg   }
1366cdc920a0Smrg
1367cdc920a0Smrg   a = get_array_entry(arrays, GL_INDEX_ARRAY, 0);
1368cdc920a0Smrg   assert(a != NULL);
1369cdc920a0Smrg   COMMON_ARRAY_DATA_INIT(a, pointer, type, stride, 1, GL_FALSE, 4, opcode);
1370cdc920a0Smrg
1371cdc920a0Smrg   if (a->enabled) {
1372cdc920a0Smrg      arrays->array_info_cache_valid = GL_FALSE;
1373cdc920a0Smrg   }
1374cdc920a0Smrg}
1375cdc920a0Smrg
1376cdc920a0Smrg
1377cdc920a0Smrgvoid
1378cdc920a0Smrg__indirect_glEdgeFlagPointer(GLsizei stride, const GLvoid * pointer)
1379cdc920a0Smrg{
13803464ebd5Sriastradh   struct glx_context *gc = __glXGetCurrentContext();
1381cdc920a0Smrg   __GLXattribute *state = (__GLXattribute *) (gc->client_state_private);
1382cdc920a0Smrg   struct array_state_vector *arrays = state->array_state;
1383cdc920a0Smrg   struct array_state *a;
1384cdc920a0Smrg
1385cdc920a0Smrg
1386cdc920a0Smrg   if (stride < 0) {
1387cdc920a0Smrg      __glXSetError(gc, GL_INVALID_VALUE);
1388cdc920a0Smrg      return;
1389cdc920a0Smrg   }
1390cdc920a0Smrg
1391cdc920a0Smrg
1392cdc920a0Smrg   a = get_array_entry(arrays, GL_EDGE_FLAG_ARRAY, 0);
1393cdc920a0Smrg   assert(a != NULL);
1394cdc920a0Smrg   COMMON_ARRAY_DATA_INIT(a, pointer, GL_UNSIGNED_BYTE, stride, 1, GL_FALSE,
1395cdc920a0Smrg                          4, X_GLrop_EdgeFlagv);
1396cdc920a0Smrg
1397cdc920a0Smrg   if (a->enabled) {
1398cdc920a0Smrg      arrays->array_info_cache_valid = GL_FALSE;
1399cdc920a0Smrg   }
1400cdc920a0Smrg}
1401cdc920a0Smrg
1402cdc920a0Smrg
1403cdc920a0Smrgvoid
1404cdc920a0Smrg__indirect_glTexCoordPointer(GLint size, GLenum type, GLsizei stride,
1405cdc920a0Smrg                             const GLvoid * pointer)
1406cdc920a0Smrg{
1407cdc920a0Smrg   static const uint16_t short_ops[5] = {
1408cdc920a0Smrg      0, X_GLrop_TexCoord1sv, X_GLrop_TexCoord2sv, X_GLrop_TexCoord3sv,
1409cdc920a0Smrg      X_GLrop_TexCoord4sv
1410cdc920a0Smrg   };
1411cdc920a0Smrg   static const uint16_t int_ops[5] = {
1412cdc920a0Smrg      0, X_GLrop_TexCoord1iv, X_GLrop_TexCoord2iv, X_GLrop_TexCoord3iv,
1413cdc920a0Smrg      X_GLrop_TexCoord4iv
1414cdc920a0Smrg   };
1415cdc920a0Smrg   static const uint16_t float_ops[5] = {
141601e04c3fSmrg      0, X_GLrop_TexCoord1fv, X_GLrop_TexCoord2fv, X_GLrop_TexCoord3fv,
1417cdc920a0Smrg      X_GLrop_TexCoord4fv
1418cdc920a0Smrg   };
1419cdc920a0Smrg   static const uint16_t double_ops[5] = {
1420cdc920a0Smrg      0, X_GLrop_TexCoord1dv, X_GLrop_TexCoord2dv, X_GLrop_TexCoord3dv,
1421cdc920a0Smrg      X_GLrop_TexCoord4dv
1422cdc920a0Smrg   };
1423cdc920a0Smrg
1424cdc920a0Smrg   static const uint16_t mshort_ops[5] = {
1425cdc920a0Smrg      0, X_GLrop_MultiTexCoord1svARB, X_GLrop_MultiTexCoord2svARB,
1426cdc920a0Smrg      X_GLrop_MultiTexCoord3svARB, X_GLrop_MultiTexCoord4svARB
1427cdc920a0Smrg   };
1428cdc920a0Smrg   static const uint16_t mint_ops[5] = {
1429cdc920a0Smrg      0, X_GLrop_MultiTexCoord1ivARB, X_GLrop_MultiTexCoord2ivARB,
1430cdc920a0Smrg      X_GLrop_MultiTexCoord3ivARB, X_GLrop_MultiTexCoord4ivARB
1431cdc920a0Smrg   };
1432cdc920a0Smrg   static const uint16_t mfloat_ops[5] = {
143301e04c3fSmrg      0, X_GLrop_MultiTexCoord1fvARB, X_GLrop_MultiTexCoord2fvARB,
1434cdc920a0Smrg      X_GLrop_MultiTexCoord3fvARB, X_GLrop_MultiTexCoord4fvARB
1435cdc920a0Smrg   };
1436cdc920a0Smrg   static const uint16_t mdouble_ops[5] = {
1437cdc920a0Smrg      0, X_GLrop_MultiTexCoord1dvARB, X_GLrop_MultiTexCoord2dvARB,
1438cdc920a0Smrg      X_GLrop_MultiTexCoord3dvARB, X_GLrop_MultiTexCoord4dvARB
1439cdc920a0Smrg   };
1440cdc920a0Smrg
1441cdc920a0Smrg   uint16_t opcode;
14423464ebd5Sriastradh   struct glx_context *gc = __glXGetCurrentContext();
1443cdc920a0Smrg   __GLXattribute *state = (__GLXattribute *) (gc->client_state_private);
1444cdc920a0Smrg   struct array_state_vector *arrays = state->array_state;
1445cdc920a0Smrg   struct array_state *a;
1446cdc920a0Smrg   unsigned header_size;
1447cdc920a0Smrg   unsigned index;
1448cdc920a0Smrg
1449cdc920a0Smrg
1450cdc920a0Smrg   if (size < 1 || size > 4 || stride < 0) {
1451cdc920a0Smrg      __glXSetError(gc, GL_INVALID_VALUE);
1452cdc920a0Smrg      return;
1453cdc920a0Smrg   }
1454cdc920a0Smrg
1455cdc920a0Smrg   index = arrays->active_texture_unit;
1456cdc920a0Smrg   if (index == 0) {
1457cdc920a0Smrg      switch (type) {
1458cdc920a0Smrg      case GL_SHORT:
1459cdc920a0Smrg         opcode = short_ops[size];
1460cdc920a0Smrg         break;
1461cdc920a0Smrg      case GL_INT:
1462cdc920a0Smrg         opcode = int_ops[size];
1463cdc920a0Smrg         break;
1464cdc920a0Smrg      case GL_FLOAT:
1465cdc920a0Smrg         opcode = float_ops[size];
1466cdc920a0Smrg         break;
1467cdc920a0Smrg      case GL_DOUBLE:
1468cdc920a0Smrg         opcode = double_ops[size];
1469cdc920a0Smrg         break;
1470cdc920a0Smrg      default:
1471cdc920a0Smrg         __glXSetError(gc, GL_INVALID_ENUM);
1472cdc920a0Smrg         return;
1473cdc920a0Smrg      }
1474cdc920a0Smrg
1475cdc920a0Smrg      header_size = 4;
1476cdc920a0Smrg   }
1477cdc920a0Smrg   else {
1478cdc920a0Smrg      switch (type) {
1479cdc920a0Smrg      case GL_SHORT:
1480cdc920a0Smrg         opcode = mshort_ops[size];
1481cdc920a0Smrg         break;
1482cdc920a0Smrg      case GL_INT:
1483cdc920a0Smrg         opcode = mint_ops[size];
1484cdc920a0Smrg         break;
1485cdc920a0Smrg      case GL_FLOAT:
1486cdc920a0Smrg         opcode = mfloat_ops[size];
1487cdc920a0Smrg         break;
1488cdc920a0Smrg      case GL_DOUBLE:
1489cdc920a0Smrg         opcode = mdouble_ops[size];
1490cdc920a0Smrg         break;
1491cdc920a0Smrg      default:
1492cdc920a0Smrg         __glXSetError(gc, GL_INVALID_ENUM);
1493cdc920a0Smrg         return;
1494cdc920a0Smrg      }
1495cdc920a0Smrg
1496cdc920a0Smrg      header_size = 8;
1497cdc920a0Smrg   }
1498cdc920a0Smrg
1499cdc920a0Smrg   a = get_array_entry(arrays, GL_TEXTURE_COORD_ARRAY, index);
1500cdc920a0Smrg   assert(a != NULL);
1501cdc920a0Smrg   COMMON_ARRAY_DATA_INIT(a, pointer, type, stride, size, GL_FALSE,
1502cdc920a0Smrg                          header_size, opcode);
1503cdc920a0Smrg
1504cdc920a0Smrg   if (a->enabled) {
1505cdc920a0Smrg      arrays->array_info_cache_valid = GL_FALSE;
1506cdc920a0Smrg   }
1507cdc920a0Smrg}
1508cdc920a0Smrg
1509cdc920a0Smrg
1510cdc920a0Smrgvoid
1511af69d88dSmrg__indirect_glSecondaryColorPointer(GLint size, GLenum type, GLsizei stride,
1512cdc920a0Smrg                                      const GLvoid * pointer)
1513cdc920a0Smrg{
1514cdc920a0Smrg   uint16_t opcode;
15153464ebd5Sriastradh   struct glx_context *gc = __glXGetCurrentContext();
1516cdc920a0Smrg   __GLXattribute *state = (__GLXattribute *) (gc->client_state_private);
1517cdc920a0Smrg   struct array_state_vector *arrays = state->array_state;
1518cdc920a0Smrg   struct array_state *a;
1519cdc920a0Smrg
1520cdc920a0Smrg
1521cdc920a0Smrg   if (size != 3 || stride < 0) {
1522cdc920a0Smrg      __glXSetError(gc, GL_INVALID_VALUE);
1523cdc920a0Smrg      return;
1524cdc920a0Smrg   }
1525cdc920a0Smrg
1526cdc920a0Smrg   switch (type) {
1527cdc920a0Smrg   case GL_BYTE:
1528cdc920a0Smrg      opcode = 4126;
1529cdc920a0Smrg      break;
1530cdc920a0Smrg   case GL_UNSIGNED_BYTE:
1531cdc920a0Smrg      opcode = 4131;
1532cdc920a0Smrg      break;
1533cdc920a0Smrg   case GL_SHORT:
1534cdc920a0Smrg      opcode = 4127;
1535cdc920a0Smrg      break;
1536cdc920a0Smrg   case GL_UNSIGNED_SHORT:
1537cdc920a0Smrg      opcode = 4132;
1538cdc920a0Smrg      break;
1539cdc920a0Smrg   case GL_INT:
1540cdc920a0Smrg      opcode = 4128;
1541cdc920a0Smrg      break;
1542cdc920a0Smrg   case GL_UNSIGNED_INT:
1543cdc920a0Smrg      opcode = 4133;
1544cdc920a0Smrg      break;
1545cdc920a0Smrg   case GL_FLOAT:
1546cdc920a0Smrg      opcode = 4129;
1547cdc920a0Smrg      break;
1548cdc920a0Smrg   case GL_DOUBLE:
1549cdc920a0Smrg      opcode = 4130;
1550cdc920a0Smrg      break;
1551cdc920a0Smrg   default:
1552cdc920a0Smrg      __glXSetError(gc, GL_INVALID_ENUM);
1553cdc920a0Smrg      return;
1554cdc920a0Smrg   }
1555cdc920a0Smrg
1556cdc920a0Smrg   a = get_array_entry(arrays, GL_SECONDARY_COLOR_ARRAY, 0);
1557cdc920a0Smrg   if (a == NULL) {
1558cdc920a0Smrg      __glXSetError(gc, GL_INVALID_OPERATION);
1559cdc920a0Smrg      return;
1560cdc920a0Smrg   }
1561cdc920a0Smrg
1562cdc920a0Smrg   COMMON_ARRAY_DATA_INIT(a, pointer, type, stride, size, GL_TRUE, 4, opcode);
1563cdc920a0Smrg
1564cdc920a0Smrg   if (a->enabled) {
1565cdc920a0Smrg      arrays->array_info_cache_valid = GL_FALSE;
1566cdc920a0Smrg   }
1567cdc920a0Smrg}
1568cdc920a0Smrg
1569cdc920a0Smrg
1570cdc920a0Smrgvoid
1571af69d88dSmrg__indirect_glFogCoordPointer(GLenum type, GLsizei stride,
1572cdc920a0Smrg                                const GLvoid * pointer)
1573cdc920a0Smrg{
1574cdc920a0Smrg   uint16_t opcode;
15753464ebd5Sriastradh   struct glx_context *gc = __glXGetCurrentContext();
1576cdc920a0Smrg   __GLXattribute *state = (__GLXattribute *) (gc->client_state_private);
1577cdc920a0Smrg   struct array_state_vector *arrays = state->array_state;
1578cdc920a0Smrg   struct array_state *a;
1579cdc920a0Smrg
1580cdc920a0Smrg
1581cdc920a0Smrg   if (stride < 0) {
1582cdc920a0Smrg      __glXSetError(gc, GL_INVALID_VALUE);
1583cdc920a0Smrg      return;
1584cdc920a0Smrg   }
1585cdc920a0Smrg
1586cdc920a0Smrg   switch (type) {
1587cdc920a0Smrg   case GL_FLOAT:
1588cdc920a0Smrg      opcode = 4124;
1589cdc920a0Smrg      break;
1590cdc920a0Smrg   case GL_DOUBLE:
1591cdc920a0Smrg      opcode = 4125;
1592cdc920a0Smrg      break;
1593cdc920a0Smrg   default:
1594cdc920a0Smrg      __glXSetError(gc, GL_INVALID_ENUM);
1595cdc920a0Smrg      return;
1596cdc920a0Smrg   }
1597cdc920a0Smrg
1598cdc920a0Smrg   a = get_array_entry(arrays, GL_FOG_COORD_ARRAY, 0);
1599cdc920a0Smrg   if (a == NULL) {
1600cdc920a0Smrg      __glXSetError(gc, GL_INVALID_OPERATION);
1601cdc920a0Smrg      return;
1602cdc920a0Smrg   }
1603cdc920a0Smrg
1604cdc920a0Smrg   COMMON_ARRAY_DATA_INIT(a, pointer, type, stride, 1, GL_FALSE, 4, opcode);
1605cdc920a0Smrg
1606cdc920a0Smrg   if (a->enabled) {
1607cdc920a0Smrg      arrays->array_info_cache_valid = GL_FALSE;
1608cdc920a0Smrg   }
1609cdc920a0Smrg}
1610cdc920a0Smrg
1611cdc920a0Smrg
1612cdc920a0Smrgvoid
1613af69d88dSmrg__indirect_glVertexAttribPointer(GLuint index, GLint size,
1614cdc920a0Smrg                                    GLenum type, GLboolean normalized,
1615cdc920a0Smrg                                    GLsizei stride, const GLvoid * pointer)
1616cdc920a0Smrg{
161701e04c3fSmrg   static const uint16_t short_ops[5] = {
161801e04c3fSmrg        0, X_GLrop_VertexAttrib1svARB, X_GLrop_VertexAttrib2svARB,
161901e04c3fSmrg        X_GLrop_VertexAttrib3svARB, X_GLrop_VertexAttrib4svARB
162001e04c3fSmrg   };
162101e04c3fSmrg   static const uint16_t float_ops[5] = {
162201e04c3fSmrg        0, X_GLrop_VertexAttrib1fvARB, X_GLrop_VertexAttrib2fvARB,
162301e04c3fSmrg        X_GLrop_VertexAttrib3fvARB, X_GLrop_VertexAttrib4fvARB
162401e04c3fSmrg   };
162501e04c3fSmrg   static const uint16_t double_ops[5] = {
162601e04c3fSmrg        0, X_GLrop_VertexAttrib1dvARB, X_GLrop_VertexAttrib2dvARB,
162701e04c3fSmrg        X_GLrop_VertexAttrib3dvARB, X_GLrop_VertexAttrib4dvARB
162801e04c3fSmrg   };
1629cdc920a0Smrg
1630cdc920a0Smrg   uint16_t opcode;
16313464ebd5Sriastradh   struct glx_context *gc = __glXGetCurrentContext();
1632cdc920a0Smrg   __GLXattribute *state = (__GLXattribute *) (gc->client_state_private);
1633cdc920a0Smrg   struct array_state_vector *arrays = state->array_state;
1634cdc920a0Smrg   struct array_state *a;
1635cdc920a0Smrg   unsigned true_immediate_count;
1636cdc920a0Smrg   unsigned true_immediate_size;
1637cdc920a0Smrg
1638cdc920a0Smrg
1639cdc920a0Smrg   if ((size < 1) || (size > 4) || (stride < 0)
1640cdc920a0Smrg       || (index > arrays->num_vertex_program_attribs)) {
1641cdc920a0Smrg      __glXSetError(gc, GL_INVALID_VALUE);
1642cdc920a0Smrg      return;
1643cdc920a0Smrg   }
1644cdc920a0Smrg
1645cdc920a0Smrg   if (normalized && (type != GL_FLOAT) && (type != GL_DOUBLE)) {
1646cdc920a0Smrg      switch (type) {
1647cdc920a0Smrg      case GL_BYTE:
1648cdc920a0Smrg         opcode = X_GLrop_VertexAttrib4NbvARB;
1649cdc920a0Smrg         break;
1650cdc920a0Smrg      case GL_UNSIGNED_BYTE:
1651cdc920a0Smrg         opcode = X_GLrop_VertexAttrib4NubvARB;
1652cdc920a0Smrg         break;
1653cdc920a0Smrg      case GL_SHORT:
1654cdc920a0Smrg         opcode = X_GLrop_VertexAttrib4NsvARB;
1655cdc920a0Smrg         break;
1656cdc920a0Smrg      case GL_UNSIGNED_SHORT:
1657cdc920a0Smrg         opcode = X_GLrop_VertexAttrib4NusvARB;
1658cdc920a0Smrg         break;
1659cdc920a0Smrg      case GL_INT:
1660cdc920a0Smrg         opcode = X_GLrop_VertexAttrib4NivARB;
1661cdc920a0Smrg         break;
1662cdc920a0Smrg      case GL_UNSIGNED_INT:
1663cdc920a0Smrg         opcode = X_GLrop_VertexAttrib4NuivARB;
1664cdc920a0Smrg         break;
1665cdc920a0Smrg      default:
1666cdc920a0Smrg         __glXSetError(gc, GL_INVALID_ENUM);
1667cdc920a0Smrg         return;
1668cdc920a0Smrg      }
1669cdc920a0Smrg
1670cdc920a0Smrg      true_immediate_count = 4;
1671cdc920a0Smrg   }
1672cdc920a0Smrg   else {
1673cdc920a0Smrg      true_immediate_count = size;
1674cdc920a0Smrg
1675cdc920a0Smrg      switch (type) {
1676cdc920a0Smrg      case GL_BYTE:
1677cdc920a0Smrg         opcode = X_GLrop_VertexAttrib4bvARB;
1678cdc920a0Smrg         true_immediate_count = 4;
1679cdc920a0Smrg         break;
1680cdc920a0Smrg      case GL_UNSIGNED_BYTE:
1681cdc920a0Smrg         opcode = X_GLrop_VertexAttrib4ubvARB;
1682cdc920a0Smrg         true_immediate_count = 4;
1683cdc920a0Smrg         break;
1684cdc920a0Smrg      case GL_SHORT:
1685cdc920a0Smrg         opcode = short_ops[size];
1686cdc920a0Smrg         break;
1687cdc920a0Smrg      case GL_UNSIGNED_SHORT:
1688cdc920a0Smrg         opcode = X_GLrop_VertexAttrib4usvARB;
1689cdc920a0Smrg         true_immediate_count = 4;
1690cdc920a0Smrg         break;
1691cdc920a0Smrg      case GL_INT:
1692cdc920a0Smrg         opcode = X_GLrop_VertexAttrib4ivARB;
1693cdc920a0Smrg         true_immediate_count = 4;
1694cdc920a0Smrg         break;
1695cdc920a0Smrg      case GL_UNSIGNED_INT:
1696cdc920a0Smrg         opcode = X_GLrop_VertexAttrib4uivARB;
1697cdc920a0Smrg         true_immediate_count = 4;
1698cdc920a0Smrg         break;
1699cdc920a0Smrg      case GL_FLOAT:
1700cdc920a0Smrg         opcode = float_ops[size];
1701cdc920a0Smrg         break;
1702cdc920a0Smrg      case GL_DOUBLE:
1703cdc920a0Smrg         opcode = double_ops[size];
1704cdc920a0Smrg         break;
1705cdc920a0Smrg      default:
1706cdc920a0Smrg         __glXSetError(gc, GL_INVALID_ENUM);
1707cdc920a0Smrg         return;
1708cdc920a0Smrg      }
1709cdc920a0Smrg   }
1710cdc920a0Smrg
1711cdc920a0Smrg   a = get_array_entry(arrays, GL_VERTEX_ATTRIB_ARRAY_POINTER, index);
1712cdc920a0Smrg   if (a == NULL) {
1713cdc920a0Smrg      __glXSetError(gc, GL_INVALID_OPERATION);
1714cdc920a0Smrg      return;
1715cdc920a0Smrg   }
1716cdc920a0Smrg
1717cdc920a0Smrg   COMMON_ARRAY_DATA_INIT(a, pointer, type, stride, size, normalized, 8,
1718cdc920a0Smrg                          opcode);
1719cdc920a0Smrg
1720cdc920a0Smrg   true_immediate_size = __glXTypeSize(type) * true_immediate_count;
172101e04c3fSmrg   a->header[0] = __GLX_PAD(8 + true_immediate_size);
1722cdc920a0Smrg
1723cdc920a0Smrg   if (a->enabled) {
1724cdc920a0Smrg      arrays->array_info_cache_valid = GL_FALSE;
1725cdc920a0Smrg   }
1726cdc920a0Smrg}
1727cdc920a0Smrg
1728cdc920a0Smrg
1729cdc920a0Smrg/**
1730cdc920a0Smrg * I don't have 100% confidence that this is correct.  The different rules
1731cdc920a0Smrg * about whether or not generic vertex attributes alias "classic" vertex
1732cdc920a0Smrg * attributes (i.e., attrib1 ?= primary color) between ARB_vertex_program,
1733cdc920a0Smrg * ARB_vertex_shader, and NV_vertex_program are a bit confusing.  My
1734cdc920a0Smrg * feeling is that the client-side doesn't have to worry about it.  The
1735cdc920a0Smrg * client just sends all the data to the server and lets the server deal
1736cdc920a0Smrg * with it.
1737cdc920a0Smrg */
1738cdc920a0Smrgvoid
1739cdc920a0Smrg__indirect_glVertexAttribPointerNV(GLuint index, GLint size,
1740cdc920a0Smrg                                   GLenum type, GLsizei stride,
1741cdc920a0Smrg                                   const GLvoid * pointer)
1742cdc920a0Smrg{
17433464ebd5Sriastradh   struct glx_context *gc = __glXGetCurrentContext();
1744cdc920a0Smrg   GLboolean normalized = GL_FALSE;
1745cdc920a0Smrg
1746cdc920a0Smrg
1747cdc920a0Smrg   switch (type) {
1748cdc920a0Smrg   case GL_UNSIGNED_BYTE:
1749cdc920a0Smrg      if (size != 4) {
1750cdc920a0Smrg         __glXSetError(gc, GL_INVALID_VALUE);
1751cdc920a0Smrg         return;
1752cdc920a0Smrg      }
1753cdc920a0Smrg      normalized = GL_TRUE;
17547ec681f3Smrg      FALLTHROUGH;
1755cdc920a0Smrg   case GL_SHORT:
1756cdc920a0Smrg   case GL_FLOAT:
1757cdc920a0Smrg   case GL_DOUBLE:
1758af69d88dSmrg      __indirect_glVertexAttribPointer(index, size, type,
1759cdc920a0Smrg                                          normalized, stride, pointer);
1760cdc920a0Smrg      return;
1761cdc920a0Smrg   default:
1762cdc920a0Smrg      __glXSetError(gc, GL_INVALID_ENUM);
1763cdc920a0Smrg      return;
1764cdc920a0Smrg   }
1765cdc920a0Smrg}
1766cdc920a0Smrg
1767cdc920a0Smrg
1768cdc920a0Smrgvoid
1769af69d88dSmrg__indirect_glClientActiveTexture(GLenum texture)
1770cdc920a0Smrg{
17713464ebd5Sriastradh   struct glx_context *const gc = __glXGetCurrentContext();
1772cdc920a0Smrg   __GLXattribute *const state =
1773cdc920a0Smrg      (__GLXattribute *) (gc->client_state_private);
1774cdc920a0Smrg   struct array_state_vector *const arrays = state->array_state;
1775cdc920a0Smrg   const GLint unit = (GLint) texture - GL_TEXTURE0;
1776cdc920a0Smrg
1777cdc920a0Smrg
1778cdc920a0Smrg   if ((unit < 0) || (unit >= arrays->num_texture_units)) {
1779cdc920a0Smrg      __glXSetError(gc, GL_INVALID_ENUM);
1780cdc920a0Smrg      return;
1781cdc920a0Smrg   }
1782cdc920a0Smrg
1783cdc920a0Smrg   arrays->active_texture_unit = unit;
1784cdc920a0Smrg}
1785cdc920a0Smrg
1786cdc920a0Smrg
1787cdc920a0Smrg/**
1788cdc920a0Smrg * Modify the enable state for the selected array
1789cdc920a0Smrg */
1790cdc920a0SmrgGLboolean
1791cdc920a0Smrg__glXSetArrayEnable(__GLXattribute * state, GLenum key, unsigned index,
1792cdc920a0Smrg                    GLboolean enable)
1793cdc920a0Smrg{
1794cdc920a0Smrg   struct array_state_vector *arrays = state->array_state;
1795cdc920a0Smrg   struct array_state *a;
1796cdc920a0Smrg
1797cdc920a0Smrg
1798cdc920a0Smrg   /* Texture coordinate arrays have an implict index set when the
1799cdc920a0Smrg    * application calls glClientActiveTexture.
1800cdc920a0Smrg    */
1801cdc920a0Smrg   if (key == GL_TEXTURE_COORD_ARRAY) {
1802cdc920a0Smrg      index = arrays->active_texture_unit;
1803cdc920a0Smrg   }
1804cdc920a0Smrg
1805cdc920a0Smrg   a = get_array_entry(arrays, key, index);
1806cdc920a0Smrg
1807cdc920a0Smrg   if ((a != NULL) && (a->enabled != enable)) {
1808cdc920a0Smrg      a->enabled = enable;
1809cdc920a0Smrg      arrays->array_info_cache_valid = GL_FALSE;
1810cdc920a0Smrg   }
1811cdc920a0Smrg
1812cdc920a0Smrg   return (a != NULL);
1813cdc920a0Smrg}
1814cdc920a0Smrg
1815cdc920a0Smrg
1816cdc920a0Smrgvoid
1817cdc920a0Smrg__glXArrayDisableAll(__GLXattribute * state)
1818cdc920a0Smrg{
1819cdc920a0Smrg   struct array_state_vector *arrays = state->array_state;
1820cdc920a0Smrg   unsigned i;
1821cdc920a0Smrg
1822cdc920a0Smrg
1823cdc920a0Smrg   for (i = 0; i < arrays->num_arrays; i++) {
1824cdc920a0Smrg      arrays->arrays[i].enabled = GL_FALSE;
1825cdc920a0Smrg   }
1826cdc920a0Smrg
1827cdc920a0Smrg   arrays->array_info_cache_valid = GL_FALSE;
1828cdc920a0Smrg}
1829cdc920a0Smrg
1830cdc920a0Smrg
1831cdc920a0Smrg/**
1832cdc920a0Smrg */
1833cdc920a0SmrgGLboolean
1834cdc920a0Smrg__glXGetArrayEnable(const __GLXattribute * const state,
1835cdc920a0Smrg                    GLenum key, unsigned index, GLintptr * dest)
1836cdc920a0Smrg{
1837cdc920a0Smrg   const struct array_state_vector *arrays = state->array_state;
1838cdc920a0Smrg   const struct array_state *a =
1839cdc920a0Smrg      get_array_entry((struct array_state_vector *) arrays,
1840cdc920a0Smrg                      key, index);
1841cdc920a0Smrg
1842cdc920a0Smrg   if (a != NULL) {
1843cdc920a0Smrg      *dest = (GLintptr) a->enabled;
1844cdc920a0Smrg   }
1845cdc920a0Smrg
1846cdc920a0Smrg   return (a != NULL);
1847cdc920a0Smrg}
1848cdc920a0Smrg
1849cdc920a0Smrg
1850cdc920a0Smrg/**
1851cdc920a0Smrg */
1852cdc920a0SmrgGLboolean
1853cdc920a0Smrg__glXGetArrayType(const __GLXattribute * const state,
1854cdc920a0Smrg                  GLenum key, unsigned index, GLintptr * dest)
1855cdc920a0Smrg{
1856cdc920a0Smrg   const struct array_state_vector *arrays = state->array_state;
1857cdc920a0Smrg   const struct array_state *a =
1858cdc920a0Smrg      get_array_entry((struct array_state_vector *) arrays,
1859cdc920a0Smrg                      key, index);
1860cdc920a0Smrg
1861cdc920a0Smrg   if (a != NULL) {
1862cdc920a0Smrg      *dest = (GLintptr) a->data_type;
1863cdc920a0Smrg   }
1864cdc920a0Smrg
1865cdc920a0Smrg   return (a != NULL);
1866cdc920a0Smrg}
1867cdc920a0Smrg
1868cdc920a0Smrg
1869cdc920a0Smrg/**
1870cdc920a0Smrg */
1871cdc920a0SmrgGLboolean
1872cdc920a0Smrg__glXGetArraySize(const __GLXattribute * const state,
1873cdc920a0Smrg                  GLenum key, unsigned index, GLintptr * dest)
1874cdc920a0Smrg{
1875cdc920a0Smrg   const struct array_state_vector *arrays = state->array_state;
1876cdc920a0Smrg   const struct array_state *a =
1877cdc920a0Smrg      get_array_entry((struct array_state_vector *) arrays,
1878cdc920a0Smrg                      key, index);
1879cdc920a0Smrg
1880cdc920a0Smrg   if (a != NULL) {
1881cdc920a0Smrg      *dest = (GLintptr) a->count;
1882cdc920a0Smrg   }
1883cdc920a0Smrg
1884cdc920a0Smrg   return (a != NULL);
1885cdc920a0Smrg}
1886cdc920a0Smrg
1887cdc920a0Smrg
1888cdc920a0Smrg/**
1889cdc920a0Smrg */
1890cdc920a0SmrgGLboolean
1891cdc920a0Smrg__glXGetArrayStride(const __GLXattribute * const state,
1892cdc920a0Smrg                    GLenum key, unsigned index, GLintptr * dest)
1893cdc920a0Smrg{
1894cdc920a0Smrg   const struct array_state_vector *arrays = state->array_state;
1895cdc920a0Smrg   const struct array_state *a =
1896cdc920a0Smrg      get_array_entry((struct array_state_vector *) arrays,
1897cdc920a0Smrg                      key, index);
1898cdc920a0Smrg
1899cdc920a0Smrg   if (a != NULL) {
1900cdc920a0Smrg      *dest = (GLintptr) a->user_stride;
1901cdc920a0Smrg   }
1902cdc920a0Smrg
1903cdc920a0Smrg   return (a != NULL);
1904cdc920a0Smrg}
1905cdc920a0Smrg
1906cdc920a0Smrg
1907cdc920a0Smrg/**
1908cdc920a0Smrg */
1909cdc920a0SmrgGLboolean
1910cdc920a0Smrg__glXGetArrayPointer(const __GLXattribute * const state,
1911cdc920a0Smrg                     GLenum key, unsigned index, void **dest)
1912cdc920a0Smrg{
1913cdc920a0Smrg   const struct array_state_vector *arrays = state->array_state;
1914cdc920a0Smrg   const struct array_state *a =
1915cdc920a0Smrg      get_array_entry((struct array_state_vector *) arrays,
1916cdc920a0Smrg                      key, index);
1917cdc920a0Smrg
1918cdc920a0Smrg
1919cdc920a0Smrg   if (a != NULL) {
1920cdc920a0Smrg      *dest = (void *) (a->data);
1921cdc920a0Smrg   }
1922cdc920a0Smrg
1923cdc920a0Smrg   return (a != NULL);
1924cdc920a0Smrg}
1925cdc920a0Smrg
1926cdc920a0Smrg
1927cdc920a0Smrg/**
1928cdc920a0Smrg */
1929cdc920a0SmrgGLboolean
1930cdc920a0Smrg__glXGetArrayNormalized(const __GLXattribute * const state,
1931cdc920a0Smrg                        GLenum key, unsigned index, GLintptr * dest)
1932cdc920a0Smrg{
1933cdc920a0Smrg   const struct array_state_vector *arrays = state->array_state;
1934cdc920a0Smrg   const struct array_state *a =
1935cdc920a0Smrg      get_array_entry((struct array_state_vector *) arrays,
1936cdc920a0Smrg                      key, index);
1937cdc920a0Smrg
1938cdc920a0Smrg
1939cdc920a0Smrg   if (a != NULL) {
1940cdc920a0Smrg      *dest = (GLintptr) a->normalized;
1941cdc920a0Smrg   }
1942cdc920a0Smrg
1943cdc920a0Smrg   return (a != NULL);
1944cdc920a0Smrg}
1945cdc920a0Smrg
1946cdc920a0Smrg
1947cdc920a0Smrg/**
1948cdc920a0Smrg */
1949cdc920a0SmrgGLuint
1950cdc920a0Smrg__glXGetActiveTextureUnit(const __GLXattribute * const state)
1951cdc920a0Smrg{
1952cdc920a0Smrg   return state->array_state->active_texture_unit;
1953cdc920a0Smrg}
1954cdc920a0Smrg
1955cdc920a0Smrg
1956cdc920a0Smrgvoid
1957cdc920a0Smrg__glXPushArrayState(__GLXattribute * state)
1958cdc920a0Smrg{
1959cdc920a0Smrg   struct array_state_vector *arrays = state->array_state;
1960cdc920a0Smrg   struct array_stack_state *stack =
1961cdc920a0Smrg      &arrays->stack[(arrays->stack_index * arrays->num_arrays)];
1962cdc920a0Smrg   unsigned i;
1963cdc920a0Smrg
1964cdc920a0Smrg   /* XXX are we pushing _all_ the necessary fields? */
1965cdc920a0Smrg   for (i = 0; i < arrays->num_arrays; i++) {
1966cdc920a0Smrg      stack[i].data = arrays->arrays[i].data;
1967cdc920a0Smrg      stack[i].data_type = arrays->arrays[i].data_type;
1968cdc920a0Smrg      stack[i].user_stride = arrays->arrays[i].user_stride;
1969cdc920a0Smrg      stack[i].count = arrays->arrays[i].count;
1970cdc920a0Smrg      stack[i].key = arrays->arrays[i].key;
1971cdc920a0Smrg      stack[i].index = arrays->arrays[i].index;
1972cdc920a0Smrg      stack[i].enabled = arrays->arrays[i].enabled;
1973cdc920a0Smrg   }
1974cdc920a0Smrg
1975cdc920a0Smrg   arrays->active_texture_unit_stack[arrays->stack_index] =
1976cdc920a0Smrg      arrays->active_texture_unit;
1977cdc920a0Smrg
1978cdc920a0Smrg   arrays->stack_index++;
1979cdc920a0Smrg}
1980cdc920a0Smrg
1981cdc920a0Smrg
1982cdc920a0Smrgvoid
1983cdc920a0Smrg__glXPopArrayState(__GLXattribute * state)
1984cdc920a0Smrg{
1985cdc920a0Smrg   struct array_state_vector *arrays = state->array_state;
1986cdc920a0Smrg   struct array_stack_state *stack;
1987cdc920a0Smrg   unsigned i;
1988cdc920a0Smrg
1989cdc920a0Smrg
1990cdc920a0Smrg   arrays->stack_index--;
1991cdc920a0Smrg   stack = &arrays->stack[(arrays->stack_index * arrays->num_arrays)];
1992cdc920a0Smrg
1993cdc920a0Smrg   for (i = 0; i < arrays->num_arrays; i++) {
1994cdc920a0Smrg      switch (stack[i].key) {
1995cdc920a0Smrg      case GL_NORMAL_ARRAY:
1996cdc920a0Smrg         __indirect_glNormalPointer(stack[i].data_type,
1997cdc920a0Smrg                                    stack[i].user_stride, stack[i].data);
1998cdc920a0Smrg         break;
1999cdc920a0Smrg      case GL_COLOR_ARRAY:
2000cdc920a0Smrg         __indirect_glColorPointer(stack[i].count,
2001cdc920a0Smrg                                   stack[i].data_type,
2002cdc920a0Smrg                                   stack[i].user_stride, stack[i].data);
2003cdc920a0Smrg         break;
2004cdc920a0Smrg      case GL_INDEX_ARRAY:
2005cdc920a0Smrg         __indirect_glIndexPointer(stack[i].data_type,
2006cdc920a0Smrg                                   stack[i].user_stride, stack[i].data);
2007cdc920a0Smrg         break;
2008cdc920a0Smrg      case GL_EDGE_FLAG_ARRAY:
2009cdc920a0Smrg         __indirect_glEdgeFlagPointer(stack[i].user_stride, stack[i].data);
2010cdc920a0Smrg         break;
2011cdc920a0Smrg      case GL_TEXTURE_COORD_ARRAY:
2012cdc920a0Smrg         arrays->active_texture_unit = stack[i].index;
2013cdc920a0Smrg         __indirect_glTexCoordPointer(stack[i].count,
2014cdc920a0Smrg                                      stack[i].data_type,
2015cdc920a0Smrg                                      stack[i].user_stride, stack[i].data);
2016cdc920a0Smrg         break;
2017cdc920a0Smrg      case GL_SECONDARY_COLOR_ARRAY:
2018af69d88dSmrg         __indirect_glSecondaryColorPointer(stack[i].count,
2019cdc920a0Smrg                                               stack[i].data_type,
2020cdc920a0Smrg                                               stack[i].user_stride,
2021cdc920a0Smrg                                               stack[i].data);
2022cdc920a0Smrg         break;
2023cdc920a0Smrg      case GL_FOG_COORDINATE_ARRAY:
2024af69d88dSmrg         __indirect_glFogCoordPointer(stack[i].data_type,
2025cdc920a0Smrg                                         stack[i].user_stride, stack[i].data);
2026cdc920a0Smrg         break;
2027cdc920a0Smrg
2028cdc920a0Smrg      }
2029cdc920a0Smrg
2030cdc920a0Smrg      __glXSetArrayEnable(state, stack[i].key, stack[i].index,
2031cdc920a0Smrg                          stack[i].enabled);
2032cdc920a0Smrg   }
2033cdc920a0Smrg
2034cdc920a0Smrg   arrays->active_texture_unit =
2035cdc920a0Smrg      arrays->active_texture_unit_stack[arrays->stack_index];
2036cdc920a0Smrg}
2037