1 /* $XFree86: xc/lib/GL/glx/vertarr.c,v 1.4 2001/03/25 05:32:00 tsi Exp $ */
3 ** License Applicability. Except to the extent portions of this file are
4 ** made subject to an alternative license as permitted in the SGI Free
5 ** Software License B, Version 1.1 (the "License"), the contents of this
6 ** file are subject only to the provisions of the License. You may not use
7 ** this file except in compliance with the License. You may obtain a copy
8 ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
9 ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
11 ** http://oss.sgi.com/projects/FreeB
13 ** Note that, as provided in the License, the Software is distributed on an
14 ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
15 ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
16 ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
17 ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
19 ** Original Code. The Original Code is: OpenGL Sample Implementation,
20 ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
21 ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
22 ** Copyright in any portions created by third parties is as indicated
23 ** elsewhere herein. All Rights Reserved.
25 ** Additional Notice Provisions: The application programming interfaces
26 ** established by SGI in conjunction with the Original Code are The
27 ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
28 ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
29 ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
30 ** Window System(R) (Version 1.3), released October 19, 1998. This software
31 ** was created using the OpenGL(R) version 1.2.1 Sample Implementation
32 ** published by SGI, but has not been independently verified as being
33 ** compliant with the OpenGL(R) version 1.2.1 Specification.
38 #include "glxclient.h"
39 #include "packrender.h"
42 #include <limits.h> /* INT_MAX */
44 /* macros for setting function pointers */
45 #define __GL_VERTEX_FUNC(NAME, let) \
48 vertexPointer->proc = (void (*)(const void *))__indirect_glVertex2##let##v; \
50 vertexPointer->proc = (void (*)(const void *))__indirect_glVertex3##let##v; \
52 vertexPointer->proc = (void (*)(const void *))__indirect_glVertex4##let##v; \
55 #define __GL_NORMAL_FUNC(NAME, let) \
57 normalPointer->proc = (void (*)(const void *))__indirect_glNormal3##let##v; \
60 #define __GL_COLOR_FUNC(NAME, let) \
63 colorPointer->proc = (void (*)(const void *))__indirect_glColor3##let##v; \
65 colorPointer->proc = (void (*)(const void *))__indirect_glColor4##let##v; \
68 #define __GL_SEC_COLOR_FUNC(NAME, let) \
70 seccolorPointer->proc = (void (*)(const void *))__indirect_glSecondaryColor3##let##vEXT; \
72 #define __GL_FOG_FUNC(NAME, let) \
74 fogPointer->proc = (void (*)(const void *))__indirect_glFogCoord##let##vEXT; \
76 #define __GL_INDEX_FUNC(NAME, let) \
78 indexPointer->proc = (void (*)(const void *))__indirect_glIndex##let##v; \
81 #define __GL_TEXTURE_FUNC(NAME, let) \
84 texCoordPointer->proc = (void (*)(const void *))__indirect_glTexCoord1##let##v; \
85 texCoordPointer->mtex_proc = (void (*)(GLenum, const void *))__indirect_glMultiTexCoord1##let##vARB; \
86 } else if (size == 2) { \
87 texCoordPointer->proc = (void (*)(const void *))__indirect_glTexCoord2##let##v; \
88 texCoordPointer->mtex_proc = (void (*)(GLenum, const void *))__indirect_glMultiTexCoord2##let##vARB; \
89 } else if (size == 3) { \
90 texCoordPointer->proc = (void (*)(const void *))__indirect_glTexCoord3##let##v; \
91 texCoordPointer->mtex_proc = (void (*)(GLenum, const void *))__indirect_glMultiTexCoord2##let##vARB; \
92 } else if (size == 4) { \
93 texCoordPointer->proc = (void (*)(const void *))__indirect_glTexCoord4##let##v; \
94 texCoordPointer->mtex_proc = (void (*)(GLenum, const void *))__indirect_glMultiTexCoord4##let##vARB; \
98 * Table of sizes, in bytes, of a GL types. All of the type enums are be in
99 * the range 0x1400 - 0x140F. That includes types added by extensions (i.e.,
100 * \c GL_HALF_FLOAT_NV). This elements of this table correspond to the
101 * type enums masked with 0x0f.
104 * \c GL_HAVE_FLOAT_NV is not included. Neither are \c GL_2_BYTES,
105 * \c GL_3_BYTES, or \c GL_4_BYTES.
107 static const GLuint __glXTypeSize_table
[16] = {
108 1, 1, 2, 2, 4, 4, 4, 0, 0, 0, 8, 0, 0, 0, 0, 0
111 #define __glXTypeSize(e) ((((e) & ~0x0f) != 0x1400) \
112 ? 0 : __glXTypeSize_table[ (e) & 0x0f ])
116 * Initialize vertex array state for a GLX context.
118 * \param gc GLX context whose vertex array state is to be initialized.
121 * Someone is going to have to check the spec. This function takes greate
122 * care to initialize the \c size and \c type fields to "correct" values
123 * for each array. I'm not sure this is necessary. I think it should be
124 * acceptable to just \c memset the whole \c arrays and \c texCoord arrays
125 * to zero and be done with it. The spec may say something to the contrary,
128 void __glXInitVertexArrayState(__GLXcontext
*gc
)
130 __GLXattribute
* state
= (__GLXattribute
*)(gc
->client_state_private
);
131 __GLXvertArrayState
*va
= &state
->vertArray
;
135 va
->texture_enables
= 0;
137 for ( i
= 0 ; i
< __GLX_MAX_ARRAYS
; i
++ ) {
138 va
->arrays
[ i
].proc
= NULL
;
139 va
->arrays
[ i
].skip
= 0;
140 va
->arrays
[ i
].ptr
= 0;
141 va
->arrays
[ i
].size
= 1;
142 va
->arrays
[ i
].type
= GL_FLOAT
;
143 va
->arrays
[ i
].stride
= 0;
146 va
->arrays
[ edgeFlag_ARRAY
].type
= GL_UNSIGNED_BYTE
;;
148 va
->arrays
[ secondaryColor_ARRAY
].size
= 3;
149 va
->arrays
[ color_ARRAY
].size
= 4;
150 va
->arrays
[ normal_ARRAY
].size
= 3;
151 va
->arrays
[ vertex_ARRAY
].size
= 4;
153 for ( i
= 0 ; i
< __GLX_MAX_TEXTURE_UNITS
; i
++ ) {
154 va
->texCoord
[ i
].proc
= NULL
;
155 va
->texCoord
[ i
].skip
= 0;
156 va
->texCoord
[ i
].ptr
= 0;
157 va
->texCoord
[ i
].size
= 4;
158 va
->texCoord
[ i
].type
= GL_FLOAT
;
159 va
->texCoord
[ i
].stride
= 0;
162 va
->maxElementsVertices
= INT_MAX
;
163 va
->maxElementsIndices
= INT_MAX
;
166 /*****************************************************************************/
169 * \name Vertex array pointer bridge functions
171 * When EXT_vertex_array was moved into the core GL spec, the \c count
172 * parameter was lost. This libGL really only wants to implement the GL 1.1
173 * version, but we need to support applications that were written to the old
174 * interface. These bridge functions are part of the glue that makes this
178 void __indirect_glColorPointerEXT(GLint size
, GLenum type
, GLsizei stride
,
179 GLsizei count
, const GLvoid
* pointer
)
181 (void) count
; __indirect_glColorPointer( size
, type
, stride
, pointer
);
184 void __indirect_glEdgeFlagPointerEXT(GLsizei stride
,
185 GLsizei count
, const GLboolean
* pointer
)
187 (void) count
; __indirect_glEdgeFlagPointer( stride
, pointer
);
190 void __indirect_glIndexPointerEXT(GLenum type
, GLsizei stride
,
191 GLsizei count
, const GLvoid
* pointer
)
193 (void) count
; __indirect_glIndexPointer( type
, stride
, pointer
);
196 void __indirect_glNormalPointerEXT(GLenum type
, GLsizei stride
, GLsizei count
,
197 const GLvoid
* pointer
)
199 (void) count
; __indirect_glNormalPointer( type
, stride
, pointer
);
202 void __indirect_glTexCoordPointerEXT(GLint size
, GLenum type
, GLsizei stride
,
203 GLsizei count
, const GLvoid
* pointer
)
205 (void) count
; __indirect_glTexCoordPointer( size
, type
, stride
, pointer
);
208 void __indirect_glVertexPointerEXT(GLint size
, GLenum type
, GLsizei stride
,
209 GLsizei count
, const GLvoid
* pointer
)
211 (void) count
; __indirect_glVertexPointer( size
, type
, stride
, pointer
);
215 /*****************************************************************************/
217 void __indirect_glVertexPointer(GLint size
, GLenum type
, GLsizei stride
,
218 const GLvoid
*pointer
)
220 __GLXcontext
*gc
= __glXGetCurrentContext();
221 __GLXattribute
* state
= (__GLXattribute
*)(gc
->client_state_private
);
222 __GLXvertexArrayPointerState
*vertexPointer
= &state
->vertArray
.arrays
[ vertex_ARRAY
];
224 /* Check arguments */
225 if (size
< 2 || size
> 4 || stride
< 0) {
226 __glXSetError(gc
, GL_INVALID_VALUE
);
230 /* Choose appropriate api proc */
232 __GL_VERTEX_FUNC(SHORT
, s
);
233 __GL_VERTEX_FUNC(INT
, i
);
234 __GL_VERTEX_FUNC(FLOAT
, f
);
235 __GL_VERTEX_FUNC(DOUBLE
, d
);
237 __glXSetError(gc
, GL_INVALID_ENUM
);
241 vertexPointer
->size
= size
;
242 vertexPointer
->type
= type
;
243 vertexPointer
->stride
= stride
;
244 vertexPointer
->ptr
= pointer
;
246 /* Set internal state */
248 vertexPointer
->skip
= __glXTypeSize(type
) * size
;
250 vertexPointer
->skip
= stride
;
254 void __indirect_glNormalPointer(GLenum type
, GLsizei stride
, const GLvoid
*pointer
)
256 __GLXcontext
*gc
= __glXGetCurrentContext();
257 __GLXattribute
* state
= (__GLXattribute
*)(gc
->client_state_private
);
258 __GLXvertexArrayPointerState
*normalPointer
= &state
->vertArray
.arrays
[ normal_ARRAY
];
260 /* Check arguments */
262 __glXSetError(gc
, GL_INVALID_VALUE
);
266 /* Choose appropriate api proc */
268 __GL_NORMAL_FUNC(BYTE
, b
);
269 __GL_NORMAL_FUNC(SHORT
, s
);
270 __GL_NORMAL_FUNC(INT
, i
);
271 __GL_NORMAL_FUNC(FLOAT
, f
);
272 __GL_NORMAL_FUNC(DOUBLE
, d
);
274 __glXSetError(gc
, GL_INVALID_ENUM
);
278 normalPointer
->type
= type
;
279 normalPointer
->stride
= stride
;
280 normalPointer
->ptr
= pointer
;
282 /* Set internal state */
284 normalPointer
->skip
= 3 * __glXTypeSize(type
);
286 normalPointer
->skip
= stride
;
290 void __indirect_glColorPointer(GLint size
, GLenum type
, GLsizei stride
,
291 const GLvoid
*pointer
)
293 __GLXcontext
*gc
= __glXGetCurrentContext();
294 __GLXattribute
* state
= (__GLXattribute
*)(gc
->client_state_private
);
295 __GLXvertexArrayPointerState
*colorPointer
= &state
->vertArray
.arrays
[ color_ARRAY
];
297 /* Check arguments */
299 __glXSetError(gc
, GL_INVALID_VALUE
);
303 /* Choose appropriate api proc */
305 __GL_COLOR_FUNC(BYTE
, b
);
306 __GL_COLOR_FUNC(UNSIGNED_BYTE
, ub
);
307 __GL_COLOR_FUNC(SHORT
, s
);
308 __GL_COLOR_FUNC(UNSIGNED_SHORT
, us
);
309 __GL_COLOR_FUNC(INT
, i
);
310 __GL_COLOR_FUNC(UNSIGNED_INT
, ui
);
311 __GL_COLOR_FUNC(FLOAT
, f
);
312 __GL_COLOR_FUNC(DOUBLE
, d
);
314 __glXSetError(gc
, GL_INVALID_ENUM
);
318 colorPointer
->size
= size
;
319 colorPointer
->type
= type
;
320 colorPointer
->stride
= stride
;
321 colorPointer
->ptr
= pointer
;
323 /* Set internal state */
325 colorPointer
->skip
= size
* __glXTypeSize(type
);
327 colorPointer
->skip
= stride
;
331 void __indirect_glIndexPointer(GLenum type
, GLsizei stride
, const GLvoid
*pointer
)
333 __GLXcontext
*gc
= __glXGetCurrentContext();
334 __GLXattribute
* state
= (__GLXattribute
*)(gc
->client_state_private
);
335 __GLXvertexArrayPointerState
*indexPointer
= &state
->vertArray
.arrays
[ index_ARRAY
];
337 /* Check arguments */
339 __glXSetError(gc
, GL_INVALID_VALUE
);
343 /* Choose appropriate api proc */
345 __GL_INDEX_FUNC(UNSIGNED_BYTE
, ub
);
346 __GL_INDEX_FUNC(SHORT
, s
);
347 __GL_INDEX_FUNC(INT
, i
);
348 __GL_INDEX_FUNC(FLOAT
, f
);
349 __GL_INDEX_FUNC(DOUBLE
, d
);
351 __glXSetError(gc
, GL_INVALID_ENUM
);
355 indexPointer
->type
= type
;
356 indexPointer
->stride
= stride
;
357 indexPointer
->ptr
= pointer
;
359 /* Set internal state */
361 indexPointer
->skip
= __glXTypeSize(type
);
363 indexPointer
->skip
= stride
;
367 void __indirect_glTexCoordPointer(GLint size
, GLenum type
, GLsizei stride
,
368 const GLvoid
*pointer
)
370 __GLXcontext
*gc
= __glXGetCurrentContext();
371 __GLXattribute
* state
= (__GLXattribute
*)(gc
->client_state_private
);
372 __GLXvertexArrayPointerState
*texCoordPointer
=
373 &state
->vertArray
.texCoord
[state
->vertArray
.activeTexture
];
375 /* Check arguments */
376 if (size
< 1 || size
> 4 || stride
< 0) {
377 __glXSetError(gc
, GL_INVALID_VALUE
);
381 /* Choose appropriate api proc */
383 __GL_TEXTURE_FUNC(SHORT
, s
);
384 __GL_TEXTURE_FUNC(INT
, i
);
385 __GL_TEXTURE_FUNC(FLOAT
, f
);
386 __GL_TEXTURE_FUNC(DOUBLE
, d
);
388 __glXSetError(gc
, GL_INVALID_ENUM
);
392 texCoordPointer
->size
= size
;
393 texCoordPointer
->type
= type
;
394 texCoordPointer
->stride
= stride
;
395 texCoordPointer
->ptr
= pointer
;
397 /* Set internal state */
399 texCoordPointer
->skip
= __glXTypeSize(type
) * size
;
401 texCoordPointer
->skip
= stride
;
405 void __indirect_glEdgeFlagPointer(GLsizei stride
, const GLvoid
*pointer
)
407 __GLXcontext
*gc
= __glXGetCurrentContext();
408 __GLXattribute
* state
= (__GLXattribute
*)(gc
->client_state_private
);
409 __GLXvertexArrayPointerState
*edgeFlagPointer
= &state
->vertArray
.arrays
[ edgeFlag_ARRAY
];
411 /* Check arguments */
413 __glXSetError(gc
, GL_INVALID_VALUE
);
417 /* Choose appropriate api proc */
418 edgeFlagPointer
->proc
= (void (*)(const void *))__indirect_glEdgeFlagv
;
420 edgeFlagPointer
->stride
= stride
;
421 edgeFlagPointer
->ptr
= pointer
;
423 /* Set internal state */
425 edgeFlagPointer
->skip
= sizeof(GLboolean
);
427 edgeFlagPointer
->skip
= stride
;
432 void __indirect_glSecondaryColorPointerEXT(GLint size
, GLenum type
, GLsizei stride
,
433 const GLvoid
* pointer
)
435 __GLXcontext
*gc
= __glXGetCurrentContext();
436 __GLXattribute
* state
= (__GLXattribute
*)(gc
->client_state_private
);
437 __GLXvertexArrayPointerState
*seccolorPointer
= &state
->vertArray
.arrays
[ secondaryColor_ARRAY
];
439 /* Check arguments */
440 if ( (stride
< 0) || (size
!= 3) ) {
441 __glXSetError(gc
, GL_INVALID_VALUE
);
445 /* Choose appropriate api proc */
447 __GL_SEC_COLOR_FUNC(BYTE
, b
);
448 __GL_SEC_COLOR_FUNC(UNSIGNED_BYTE
, ub
);
449 __GL_SEC_COLOR_FUNC(SHORT
, s
);
450 __GL_SEC_COLOR_FUNC(UNSIGNED_SHORT
, us
);
451 __GL_SEC_COLOR_FUNC(INT
, i
);
452 __GL_SEC_COLOR_FUNC(UNSIGNED_INT
, ui
);
453 __GL_SEC_COLOR_FUNC(FLOAT
, f
);
454 __GL_SEC_COLOR_FUNC(DOUBLE
, d
);
456 __glXSetError(gc
, GL_INVALID_ENUM
);
460 seccolorPointer
->size
= size
;
461 seccolorPointer
->type
= type
;
462 seccolorPointer
->stride
= stride
;
463 seccolorPointer
->ptr
= pointer
;
465 /* Set internal state */
467 seccolorPointer
->skip
= size
* __glXTypeSize(type
);
469 seccolorPointer
->skip
= stride
;
473 void __indirect_glFogCoordPointerEXT(GLenum type
, GLsizei stride
, const GLvoid
* pointer
)
475 __GLXcontext
*gc
= __glXGetCurrentContext();
476 __GLXattribute
* state
= (__GLXattribute
*)(gc
->client_state_private
);
477 __GLXvertexArrayPointerState
*fogPointer
= &state
->vertArray
.arrays
[ fogCoord_ARRAY
];
479 /* Check arguments */
481 __glXSetError(gc
, GL_INVALID_VALUE
);
485 /* Choose appropriate api proc */
487 __GL_FOG_FUNC(FLOAT
, f
);
488 __GL_FOG_FUNC(DOUBLE
, d
);
490 __glXSetError(gc
, GL_INVALID_ENUM
);
494 fogPointer
->size
= 1;
495 fogPointer
->type
= type
;
496 fogPointer
->stride
= stride
;
497 fogPointer
->ptr
= pointer
;
499 /* Set internal state */
501 fogPointer
->skip
= __glXTypeSize(type
);
503 fogPointer
->skip
= stride
;
507 void __indirect_glInterleavedArrays(GLenum format
, GLsizei stride
, const GLvoid
*pointer
)
509 __GLXcontext
*gc
= __glXGetCurrentContext();
510 __GLXattribute
* state
= (__GLXattribute
*)(gc
->client_state_private
);
511 GLboolean tEnable
= GL_FALSE
, cEnable
= GL_FALSE
, nEnable
= GL_FALSE
;
512 GLenum tType
= GL_FLOAT
, nType
= GL_FLOAT
, vType
= GL_FLOAT
;
513 GLenum cType
= GL_FALSE
;
514 GLint tSize
= 0, cSize
= 0, nSize
= 3, vSize
;
515 int cOffset
= 0, nOffset
= 0, vOffset
= 0;
516 GLint trueStride
, size
;
521 size
= __glXTypeSize(vType
) * vSize
;
525 size
= __glXTypeSize(vType
) * vSize
;
530 cType
= GL_UNSIGNED_BYTE
;
532 vOffset
= __glXTypeSize(cType
) * cSize
;
533 size
= vOffset
+ __glXTypeSize(vType
) * vSize
;
538 cType
= GL_UNSIGNED_BYTE
;
540 vOffset
= __glXTypeSize(vType
) * cSize
;
541 size
= vOffset
+ __glXTypeSize(vType
) * vSize
;
548 vOffset
= __glXTypeSize(cType
) * cSize
;
549 size
= vOffset
+ __glXTypeSize(vType
) * vSize
;
554 vOffset
= __glXTypeSize(nType
) * nSize
;
555 size
= vOffset
+ __glXTypeSize(vType
) * vSize
;
562 nOffset
= __glXTypeSize(cType
) * cSize
;
564 vOffset
= nOffset
+ __glXTypeSize(nType
) * nSize
;
565 size
= vOffset
+ __glXTypeSize(vType
) * vSize
;
571 vOffset
= __glXTypeSize(tType
) * tSize
;
572 size
= vOffset
+ __glXTypeSize(vType
) * vSize
;
578 vOffset
= __glXTypeSize(tType
) * tSize
;
579 size
= vOffset
+ __glXTypeSize(vType
) * vSize
;
581 case GL_T2F_C4UB_V3F
:
586 cType
= GL_UNSIGNED_BYTE
;
587 cOffset
= __glXTypeSize(tType
) * tSize
;
589 vOffset
= cOffset
+ __glXTypeSize(cType
) * cSize
;
590 size
= vOffset
+ __glXTypeSize(vType
) * vSize
;
598 cOffset
= __glXTypeSize(tType
) * tSize
;
600 vOffset
= cOffset
+ __glXTypeSize(cType
) * cSize
;
601 size
= vOffset
+ __glXTypeSize(vType
) * vSize
;
607 nOffset
= __glXTypeSize(tType
) * tSize
;
609 vOffset
= nOffset
+ __glXTypeSize(nType
) * nSize
;
610 size
= vOffset
+ __glXTypeSize(vType
) * vSize
;
612 case GL_T2F_C4F_N3F_V3F
:
618 cOffset
= __glXTypeSize(tType
) * tSize
;
620 nOffset
= cOffset
+ __glXTypeSize(cType
) * cSize
;
622 vOffset
= nOffset
+ __glXTypeSize(nType
) * nSize
;
623 size
= vOffset
+ __glXTypeSize(vType
) * vSize
;
625 case GL_T4F_C4F_N3F_V4F
:
631 cOffset
= __glXTypeSize(tType
) * tSize
;
633 nOffset
= cOffset
+ __glXTypeSize(cType
) * cSize
;
635 vOffset
= nOffset
+ __glXTypeSize(nType
) * nSize
;
636 size
= vOffset
+ __glXTypeSize(vType
) * vSize
;
639 __glXSetError(gc
, GL_INVALID_ENUM
);
643 trueStride
= (stride
== 0) ? size
: stride
;
645 state
->vertArray
.enables
= 0;
646 state
->vertArray
.texture_enables
= 0;
648 __indirect_glEnableClientState(GL_TEXTURE_COORD_ARRAY
);
649 __indirect_glTexCoordPointer(tSize
, tType
, trueStride
, (const char *)pointer
);
652 __indirect_glEnableClientState(GL_COLOR_ARRAY
);
653 __indirect_glColorPointer(cSize
, cType
, trueStride
, (const char *)pointer
+cOffset
);
656 __indirect_glEnableClientState(GL_NORMAL_ARRAY
);
657 __indirect_glNormalPointer(nType
, trueStride
, (const char *)pointer
+nOffset
);
659 __indirect_glEnableClientState(GL_VERTEX_ARRAY
);
660 __indirect_glVertexPointer(vSize
, vType
, trueStride
, (const char *)pointer
+vOffset
);
663 /*****************************************************************************/
665 void __indirect_glArrayElement(GLint i
)
667 __GLXcontext
*gc
= __glXGetCurrentContext();
668 __GLXattribute
* state
= (__GLXattribute
*)(gc
->client_state_private
);
669 __GLXvertArrayState
*va
= &state
->vertArray
;
673 if (IS_TEXARRAY_ENABLED(state
, 0)) {
674 (*va
->texCoord
[0].proc
)(va
->texCoord
[0].ptr
+i
*va
->texCoord
[0].skip
);
677 /* Multitexturing is handled specially because the protocol
678 * requires an extra parameter.
680 for (j
=1; j
<__GLX_MAX_TEXTURE_UNITS
; ++j
) {
681 if (IS_TEXARRAY_ENABLED(state
, j
)) {
682 (*va
->texCoord
[j
].mtex_proc
)(GL_TEXTURE0
+ j
, va
->texCoord
[j
].ptr
+i
*va
->texCoord
[j
].skip
);
686 for ( j
= 0 ; j
< __GLX_MAX_ARRAYS
; j
++ ) {
687 if (IS_ARRAY_ENABLED_BY_INDEX(state
, j
)) {
688 (*va
->arrays
[ j
].proc
)(va
->arrays
[ j
].ptr
+i
*va
->arrays
[ j
].skip
);
695 __GLXdispatchDrawArraysComponentHeader ai
;
703 * Initialize a \c array_info structure for each array that is enabled in
704 * \c state. Determine how many arrays are enabled, and store the result
705 * in \c num_arrays. Determine how big each vertex is, and store the result
706 * in \c total_vertex_size.
708 * \returns The size of the final request. This is the size, in bytes, of
709 * the DrawArrays header, the ARRAY_INFO structures, and all the vertex data.
710 * This value \b assumes a \c X_GLXRender command is used. The true size
711 * will be 4 bytes larger if a \c X_GLXRenderLarge command is used.
714 prep_arrays(const __GLXattribute
* const state
, struct array_info
* arrays
,
716 GLsizei
*num_arrays
, GLsizei
*total_vertex_size
)
721 #define ASSIGN_ARRAY_INFO(state, enum_name, arr) \
723 arrays[ na ].ai.datatype = state->vertArray. arr .type ; \
724 arrays[ na ].ai.numVals = state->vertArray. arr .size ; \
725 arrays[ na ].ai.component = GL_ ## enum_name ## _ARRAY; \
727 arrays[ na ].bytes = state->vertArray. arr .size \
728 * __glXTypeSize( state->vertArray. arr .type ); \
729 arrays[ na ].ptr = state->vertArray. arr .ptr; \
730 arrays[ na ].skip = state->vertArray. arr .skip; \
732 vs += __GLX_PAD(arrays[ na ].bytes); \
736 #define ADD_ARRAY_IF_ENABLED(state, enum_name, arr) \
737 do { if ( IS_ARRAY_ENABLED(state, arr) ) { \
738 ASSIGN_ARRAY_INFO(state, enum_name, arrays[ arr ## _ARRAY ] ); \
741 ADD_ARRAY_IF_ENABLED(state
, VERTEX
, vertex
);
742 ADD_ARRAY_IF_ENABLED(state
, NORMAL
, normal
);
743 ADD_ARRAY_IF_ENABLED(state
, COLOR
, color
);
744 ADD_ARRAY_IF_ENABLED(state
, SECONDARY_COLOR
, secondaryColor
);
745 ADD_ARRAY_IF_ENABLED(state
, FOG_COORD
, fogCoord
);
746 ADD_ARRAY_IF_ENABLED(state
, EDGE_FLAG
, edgeFlag
);
747 ADD_ARRAY_IF_ENABLED(state
, INDEX
, index
);
749 /* The standard DrawArrays protocol *only* supports a single array of
750 * texture coordinates.
752 if ( IS_TEXARRAY_ENABLED(state
, 0) ) {
753 ASSIGN_ARRAY_INFO(state
, TEXTURE_COORD
, texCoord
[0]);
757 *total_vertex_size
= vs
;
759 return __GLX_PAD((__GLX_COMPONENT_HDR_SIZE
* na
)
761 + __GLX_DRAWARRAYS_CMD_HDR_SIZE
);
766 * Emits the vertex data for the DrawArrays GLX protocol.
769 emit_vertex(GLubyte
* data
, const struct array_info
* arrays
,
770 GLsizei num_arrays
, GLint element
, GLsizei offset
)
774 for ( i
= 0 ; i
< num_arrays
; i
++ ) {
775 (void) memcpy( data
+ offset
,
776 arrays
[i
].ptr
+ (arrays
[i
].skip
* element
),
778 offset
+= __GLX_PAD(arrays
[i
].bytes
);
786 emit_header(GLubyte
* pc
, const struct array_info
* arrays
,
787 GLsizei num_arrays
, GLsizei count
, GLenum mode
)
789 __GLXdispatchDrawArraysComponentHeader
*arrayInfo
;
792 __GLX_PUT_LONG(0, count
);
793 __GLX_PUT_LONG(4, num_arrays
);
794 __GLX_PUT_LONG(8, mode
);
796 arrayInfo
= (__GLXdispatchDrawArraysComponentHeader
*)
797 (pc
+ __GLX_DRAWARRAYS_HDR_SIZE
);
800 /* Write the ARRAY_INFO data.
803 for ( i
= 0 ; i
< num_arrays
; i
++ ) {
804 arrayInfo
[i
] = arrays
[i
].ai
;
810 * Emit GLX DrawArrays protocol using a GLXRender packet.
813 emit_Render_DrawArrays(__GLXcontext
* gc
, const struct array_info
* arrays
,
814 GLsizei first
, GLsizei count
, GLsizei num_arrays
, GLenum mode
,
815 GLsizei cmdlen
, GLsizei total_vertex_size
)
817 GLubyte
* pc
= gc
->pc
;
821 __GLX_BEGIN_VARIABLE(X_GLrop_DrawArrays
, cmdlen
);
822 emit_header(pc
+ 4, arrays
, num_arrays
, count
, mode
);
825 /* Write the actual array data.
828 offset
= __GLX_DRAWARRAYS_CMD_HDR_SIZE
829 + (num_arrays
* __GLX_COMPONENT_HDR_SIZE
);
830 for ( i
= 0 ; i
< count
; i
++ ) {
831 offset
= emit_vertex(pc
, arrays
, num_arrays
, i
+ first
, offset
);
839 * Emit GLX DrawArrays protocol using a GLXRenderLarge packet.
842 emit_RenderLarge_DrawArrays(__GLXcontext
* gc
, const struct array_info
* arrays
,
843 GLsizei first
, GLsizei count
, GLsizei num_arrays
, GLenum mode
,
844 GLsizei cmdlen
, GLsizei total_vertex_size
)
846 GLubyte
* pc
= gc
->pc
;
852 GLsizei elements_per_request
;
855 /* Calculate the maximum amount of data can be stuffed into a single
856 * packet. sz_xGLXRenderReq is added because bufSize is the maximum
857 * packet size minus sz_xGLXRenderReq.
859 * The important value here is elements_per_request. This is the number
860 * of complete array elements that will fit in a single buffer. There
861 * may be some wasted space at the end of the buffer, but splitting
862 * elements across buffer boundries would be painful.
865 maxSize
= (gc
->bufSize
+ sz_xGLXRenderReq
) - sz_xGLXRenderLargeReq
;
867 elements_per_request
= maxSize
/ total_vertex_size
;
869 totalRequests
= ((count
+ (elements_per_request
- 1))
870 / elements_per_request
) + 1;
873 /* Fill in the header data and send it away.
876 __GLX_BEGIN_VARIABLE_LARGE(X_GLrop_DrawArrays
, cmdlen
+4);
877 emit_header(pc
+ 8, arrays
, num_arrays
, count
, mode
);
879 gc
->pc
= pc
+ (__GLX_DRAWARRAYS_CMD_HDR_SIZE
+ 4)
880 + (__GLX_COMPONENT_HDR_SIZE
* num_arrays
);
881 __glXSendLargeChunk(gc
, 1, totalRequests
, gc
->buf
, gc
->pc
- gc
->buf
);
884 /* Write the actual array data.
888 for ( i
= 0 ; i
< count
; i
++ ) {
889 if ( i
== elements_per_request
) {
890 __glXSendLargeChunk(gc
, requestNumber
, totalRequests
,
900 offset
= emit_vertex(gc
->buf
, arrays
, num_arrays
, i
+ first
, offset
);
903 /* If the buffer isn't empty, emit the last, partial request.
906 assert(requestNumber
== totalRequests
);
907 __glXSendLargeChunk(gc
, requestNumber
, totalRequests
, gc
->buf
, offset
);
915 * Emit DrawArrays protocol. This function acts as a switch betteen
916 * \c emit_Render_DrawArrays and \c emit_RenderLarge_DrawArrays depending
917 * on how much array data is to be sent.
920 emit_DrawArraysEXT(const __GLXattribute
* const state
,
921 GLint first
, GLsizei count
, GLenum mode
)
923 struct array_info arrays
[32];
925 GLsizei total_vertex_size
;
926 __GLXcontext
*gc
= __glXGetCurrentContext();
930 /* Determine how big the final request will be. This depends on a number
931 * of factors. It depends on how many array elemets there are (which is
932 * the passed-in 'count'), how many arrays are enabled, how many elements
933 * are in each array entry, and what the types are for each array.
936 cmdlen
= prep_arrays(state
, arrays
, count
, & num_arrays
,
937 & total_vertex_size
);
940 /* If the data payload and the protocol header is too large for a Render
941 * command, use a RenderLarge command.
943 if (cmdlen
> gc
->maxSmallRenderCommandSize
) {
944 emit_RenderLarge_DrawArrays(gc
, arrays
, first
, count
, num_arrays
,
945 mode
, cmdlen
, total_vertex_size
);
948 emit_Render_DrawArrays(gc
, arrays
, first
, count
, num_arrays
,
949 mode
, cmdlen
, total_vertex_size
);
955 * Emit a DrawArrays call using the old "protocol." This isn't really
956 * DrawArrays protocol at all. It just simulates DrawArrays by using
957 * immediate-mode vertex calls. Very, very slow for large arrays, but works
958 * with every GLX server.
961 emit_DrawArrays_old(const __GLXattribute
* const state
,
962 GLint first
, GLsizei count
, GLenum mode
)
964 const __GLXvertArrayState
*va
= &state
->vertArray
;
965 const GLubyte
*vaPtr
[__GLX_MAX_ARRAYS
];
966 const GLubyte
*tcaPtr
[__GLX_MAX_TEXTURE_UNITS
];
970 ** Set up pointers for quick array traversal.
973 (void) memset( vaPtr
, 0, sizeof(vaPtr
) );
974 (void) memset( tcaPtr
, 0, sizeof(tcaPtr
) );
976 for ( j
= 0 ; j
< __GLX_MAX_ARRAYS
; j
++ ) {
977 if (IS_ARRAY_ENABLED_BY_INDEX(state
, j
)) {
978 vaPtr
[ j
] = va
->arrays
[ j
].ptr
+ first
* va
->arrays
[ j
].skip
;
982 for ( j
= 0 ; j
< __GLX_MAX_TEXTURE_UNITS
; j
++ ) {
983 if (IS_TEXARRAY_ENABLED(state
, j
))
984 tcaPtr
[ j
] = va
->texCoord
[ j
].ptr
+ first
* va
->texCoord
[ j
].skip
;
987 __indirect_glBegin(mode
);
988 for (i
= 0; i
< count
; i
++) {
989 if (IS_TEXARRAY_ENABLED(state
, 0)) {
990 (*va
->texCoord
[0].proc
)(tcaPtr
[0]);
991 tcaPtr
[0] += va
->texCoord
[0].skip
;
994 /* Multitexturing is handled specially because the protocol
995 * requires an extra parameter.
997 for (j
=1; j
<__GLX_MAX_TEXTURE_UNITS
; ++j
) {
998 if (IS_TEXARRAY_ENABLED(state
, j
)) {
999 (*va
->texCoord
[j
].mtex_proc
)(GL_TEXTURE0
+ j
, tcaPtr
[j
]);
1000 tcaPtr
[j
] += va
->texCoord
[j
].skip
;
1004 for ( j
= 0 ; j
< __GLX_MAX_ARRAYS
; j
++ ) {
1005 if (IS_ARRAY_ENABLED_BY_INDEX(state
, j
)) {
1006 (*va
->arrays
[ j
].proc
)(vaPtr
[ j
]);
1007 vaPtr
[ j
] += va
->arrays
[ j
].skip
;
1016 * Validate that the \c mode and \c count parameters to \c glDrawArrays or
1017 * \c glDrawElements are valid. If the arguments are not valid, then an
1018 * error code is set in the GLX context.
1020 * \returns \c GL_TRUE if the arguments are valide, \c GL_FALSE if they are
1024 glx_validate_array_args(__GLXcontext
*gc
, GLenum mode
, GLsizei count
)
1031 case GL_TRIANGLE_STRIP
:
1032 case GL_TRIANGLE_FAN
:
1039 __glXSetError(gc
, GL_INVALID_ENUM
);
1044 __glXSetError(gc
, GL_INVALID_VALUE
);
1052 void __indirect_glDrawArrays(GLenum mode
, GLint first
, GLsizei count
)
1054 __GLXcontext
*gc
= __glXGetCurrentContext();
1055 const __GLXattribute
* state
=
1056 (const __GLXattribute
*)(gc
->client_state_private
);
1059 if ( ! glx_validate_array_args(gc
, mode
, count
) ) {
1063 /* The "true" DrawArrays protocol does not support generic attributes,
1064 * multiple vertex arrays, or multiple texture coordinate arrays.
1066 if ( state
->NoDrawArraysProtocol
1067 || (state
->vertArray
.texture_enables
> 1) ) {
1068 emit_DrawArrays_old(state
, first
, count
, mode
);
1071 emit_DrawArraysEXT(state
, first
, count
, mode
);
1077 * \todo Modify this to use the "true" DrawArrays protocol if possible. This
1078 * would probably require refactoring out parts of \c emit_DrawArraysEXT into
1079 * more general functions that could be used in either place.
1081 void __indirect_glDrawElements(GLenum mode
, GLsizei count
, GLenum type
,
1082 const GLvoid
*indices
)
1084 __GLXcontext
*gc
= __glXGetCurrentContext();
1085 __GLXattribute
* state
= (__GLXattribute
*)(gc
->client_state_private
);
1086 __GLXvertArrayState
*va
= &state
->vertArray
;
1087 const GLubyte
*iPtr1
= NULL
;
1088 const GLushort
*iPtr2
= NULL
;
1089 const GLuint
*iPtr3
= NULL
;
1090 GLint i
, j
, offset
= 0;
1092 if ( ! glx_validate_array_args(gc
, mode
, count
) ) {
1097 case GL_UNSIGNED_BYTE
:
1098 iPtr1
= (const GLubyte
*)indices
;
1100 case GL_UNSIGNED_SHORT
:
1101 iPtr2
= (const GLushort
*)indices
;
1103 case GL_UNSIGNED_INT
:
1104 iPtr3
= (const GLuint
*)indices
;
1107 __glXSetError(gc
, GL_INVALID_ENUM
);
1111 __indirect_glBegin(mode
);
1112 for (i
= 0; i
< count
; i
++) {
1114 case GL_UNSIGNED_BYTE
:
1115 offset
= (GLint
)(*iPtr1
++);
1117 case GL_UNSIGNED_SHORT
:
1118 offset
= (GLint
)(*iPtr2
++);
1120 case GL_UNSIGNED_INT
:
1121 offset
= (GLint
)(*iPtr3
++);
1125 if (IS_TEXARRAY_ENABLED(state
, 0)) {
1126 (*va
->texCoord
[0].proc
)(va
->texCoord
[0].ptr
+
1127 (offset
*va
->texCoord
[0].skip
));
1130 /* Multitexturing is handled specially because the protocol
1131 * requires an extra parameter.
1133 for (j
=1; j
<__GLX_MAX_TEXTURE_UNITS
; ++j
) {
1134 if (IS_TEXARRAY_ENABLED(state
, j
)) {
1135 (*va
->texCoord
[j
].mtex_proc
)(GL_TEXTURE0
+ j
,
1136 va
->texCoord
[j
].ptr
+
1137 (offset
*va
->texCoord
[j
].skip
));
1141 for ( j
= 0 ; j
< __GLX_MAX_ARRAYS
; j
++ ) {
1142 if (IS_ARRAY_ENABLED_BY_INDEX(state
, j
)) {
1143 (*va
->arrays
[ j
].proc
)(va
->arrays
[ j
].ptr
1144 +(offset
*va
->arrays
[ j
].skip
));
1151 void __indirect_glDrawRangeElements(GLenum mode
, GLuint start
, GLuint end
,
1152 GLsizei count
, GLenum type
,
1153 const GLvoid
*indices
)
1155 __GLXcontext
*gc
= __glXGetCurrentContext();
1158 __glXSetError(gc
, GL_INVALID_VALUE
);
1162 __indirect_glDrawElements(mode
,count
,type
,indices
);
1165 void __indirect_glMultiDrawArraysEXT(GLenum mode
, GLint
*first
, GLsizei
*count
,
1170 for(i
=0; i
<primcount
; i
++) {
1171 if ( count
[i
] > 0 ) {
1172 __indirect_glDrawArrays( mode
, first
[i
], count
[i
] );
1177 void __indirect_glMultiDrawElementsEXT(GLenum mode
, const GLsizei
*count
,
1178 GLenum type
, const GLvoid
** indices
,
1183 for(i
=0; i
<primcount
; i
++) {
1184 if ( count
[i
] > 0 ) {
1185 __indirect_glDrawElements( mode
, count
[i
], type
, indices
[i
] );
1190 void __indirect_glClientActiveTextureARB(GLenum texture
)
1192 __GLXcontext
*gc
= __glXGetCurrentContext();
1193 __GLXattribute
* state
= (__GLXattribute
*)(gc
->client_state_private
);
1194 GLint unit
= (GLint
) texture
- GL_TEXTURE0
;
1196 if (unit
< 0 || __GLX_MAX_TEXTURE_UNITS
<= unit
) {
1197 __glXSetError(gc
, GL_INVALID_ENUM
);
1200 state
->vertArray
.activeTexture
= unit
;