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