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 /*****************************************************************************/
168 void __indirect_glVertexPointer(GLint size
, GLenum type
, GLsizei stride
,
169 const GLvoid
*pointer
)
171 __GLXcontext
*gc
= __glXGetCurrentContext();
172 __GLXattribute
* state
= (__GLXattribute
*)(gc
->client_state_private
);
173 __GLXvertexArrayPointerState
*vertexPointer
= &state
->vertArray
.arrays
[ vertex_ARRAY
];
175 /* Check arguments */
176 if (size
< 2 || size
> 4 || stride
< 0) {
177 __glXSetError(gc
, GL_INVALID_VALUE
);
181 /* Choose appropriate api proc */
183 __GL_VERTEX_FUNC(SHORT
, s
);
184 __GL_VERTEX_FUNC(INT
, i
);
185 __GL_VERTEX_FUNC(FLOAT
, f
);
186 __GL_VERTEX_FUNC(DOUBLE
, d
);
188 __glXSetError(gc
, GL_INVALID_ENUM
);
192 vertexPointer
->size
= size
;
193 vertexPointer
->type
= type
;
194 vertexPointer
->stride
= stride
;
195 vertexPointer
->ptr
= pointer
;
197 /* Set internal state */
199 vertexPointer
->skip
= __glXTypeSize(type
) * size
;
201 vertexPointer
->skip
= stride
;
205 void __indirect_glNormalPointer(GLenum type
, GLsizei stride
, const GLvoid
*pointer
)
207 __GLXcontext
*gc
= __glXGetCurrentContext();
208 __GLXattribute
* state
= (__GLXattribute
*)(gc
->client_state_private
);
209 __GLXvertexArrayPointerState
*normalPointer
= &state
->vertArray
.arrays
[ normal_ARRAY
];
211 /* Check arguments */
213 __glXSetError(gc
, GL_INVALID_VALUE
);
217 /* Choose appropriate api proc */
219 __GL_NORMAL_FUNC(BYTE
, b
);
220 __GL_NORMAL_FUNC(SHORT
, s
);
221 __GL_NORMAL_FUNC(INT
, i
);
222 __GL_NORMAL_FUNC(FLOAT
, f
);
223 __GL_NORMAL_FUNC(DOUBLE
, d
);
225 __glXSetError(gc
, GL_INVALID_ENUM
);
229 normalPointer
->type
= type
;
230 normalPointer
->stride
= stride
;
231 normalPointer
->ptr
= pointer
;
233 /* Set internal state */
235 normalPointer
->skip
= 3 * __glXTypeSize(type
);
237 normalPointer
->skip
= stride
;
241 void __indirect_glColorPointer(GLint size
, GLenum type
, GLsizei stride
,
242 const GLvoid
*pointer
)
244 __GLXcontext
*gc
= __glXGetCurrentContext();
245 __GLXattribute
* state
= (__GLXattribute
*)(gc
->client_state_private
);
246 __GLXvertexArrayPointerState
*colorPointer
= &state
->vertArray
.arrays
[ color_ARRAY
];
248 /* Check arguments */
250 __glXSetError(gc
, GL_INVALID_VALUE
);
254 /* Choose appropriate api proc */
256 __GL_COLOR_FUNC(BYTE
, b
);
257 __GL_COLOR_FUNC(UNSIGNED_BYTE
, ub
);
258 __GL_COLOR_FUNC(SHORT
, s
);
259 __GL_COLOR_FUNC(UNSIGNED_SHORT
, us
);
260 __GL_COLOR_FUNC(INT
, i
);
261 __GL_COLOR_FUNC(UNSIGNED_INT
, ui
);
262 __GL_COLOR_FUNC(FLOAT
, f
);
263 __GL_COLOR_FUNC(DOUBLE
, d
);
265 __glXSetError(gc
, GL_INVALID_ENUM
);
269 colorPointer
->size
= size
;
270 colorPointer
->type
= type
;
271 colorPointer
->stride
= stride
;
272 colorPointer
->ptr
= pointer
;
274 /* Set internal state */
276 colorPointer
->skip
= size
* __glXTypeSize(type
);
278 colorPointer
->skip
= stride
;
282 void __indirect_glIndexPointer(GLenum type
, GLsizei stride
, const GLvoid
*pointer
)
284 __GLXcontext
*gc
= __glXGetCurrentContext();
285 __GLXattribute
* state
= (__GLXattribute
*)(gc
->client_state_private
);
286 __GLXvertexArrayPointerState
*indexPointer
= &state
->vertArray
.arrays
[ index_ARRAY
];
288 /* Check arguments */
290 __glXSetError(gc
, GL_INVALID_VALUE
);
294 /* Choose appropriate api proc */
296 __GL_INDEX_FUNC(UNSIGNED_BYTE
, ub
);
297 __GL_INDEX_FUNC(SHORT
, s
);
298 __GL_INDEX_FUNC(INT
, i
);
299 __GL_INDEX_FUNC(FLOAT
, f
);
300 __GL_INDEX_FUNC(DOUBLE
, d
);
302 __glXSetError(gc
, GL_INVALID_ENUM
);
306 indexPointer
->type
= type
;
307 indexPointer
->stride
= stride
;
308 indexPointer
->ptr
= pointer
;
310 /* Set internal state */
312 indexPointer
->skip
= __glXTypeSize(type
);
314 indexPointer
->skip
= stride
;
318 void __indirect_glTexCoordPointer(GLint size
, GLenum type
, GLsizei stride
,
319 const GLvoid
*pointer
)
321 __GLXcontext
*gc
= __glXGetCurrentContext();
322 __GLXattribute
* state
= (__GLXattribute
*)(gc
->client_state_private
);
323 __GLXvertexArrayPointerState
*texCoordPointer
=
324 &state
->vertArray
.texCoord
[state
->vertArray
.activeTexture
];
326 /* Check arguments */
327 if (size
< 1 || size
> 4 || stride
< 0) {
328 __glXSetError(gc
, GL_INVALID_VALUE
);
332 /* Choose appropriate api proc */
334 __GL_TEXTURE_FUNC(SHORT
, s
);
335 __GL_TEXTURE_FUNC(INT
, i
);
336 __GL_TEXTURE_FUNC(FLOAT
, f
);
337 __GL_TEXTURE_FUNC(DOUBLE
, d
);
339 __glXSetError(gc
, GL_INVALID_ENUM
);
343 texCoordPointer
->size
= size
;
344 texCoordPointer
->type
= type
;
345 texCoordPointer
->stride
= stride
;
346 texCoordPointer
->ptr
= pointer
;
348 /* Set internal state */
350 texCoordPointer
->skip
= __glXTypeSize(type
) * size
;
352 texCoordPointer
->skip
= stride
;
356 void __indirect_glEdgeFlagPointer(GLsizei stride
, const GLvoid
*pointer
)
358 __GLXcontext
*gc
= __glXGetCurrentContext();
359 __GLXattribute
* state
= (__GLXattribute
*)(gc
->client_state_private
);
360 __GLXvertexArrayPointerState
*edgeFlagPointer
= &state
->vertArray
.arrays
[ edgeFlag_ARRAY
];
362 /* Check arguments */
364 __glXSetError(gc
, GL_INVALID_VALUE
);
368 /* Choose appropriate api proc */
369 edgeFlagPointer
->proc
= (void (*)(const void *))__indirect_glEdgeFlagv
;
371 edgeFlagPointer
->stride
= stride
;
372 edgeFlagPointer
->ptr
= pointer
;
374 /* Set internal state */
376 edgeFlagPointer
->skip
= sizeof(GLboolean
);
378 edgeFlagPointer
->skip
= stride
;
383 void __indirect_glSecondaryColorPointerEXT(GLint size
, GLenum type
, GLsizei stride
,
384 const GLvoid
* pointer
)
386 __GLXcontext
*gc
= __glXGetCurrentContext();
387 __GLXattribute
* state
= (__GLXattribute
*)(gc
->client_state_private
);
388 __GLXvertexArrayPointerState
*seccolorPointer
= &state
->vertArray
.arrays
[ secondaryColor_ARRAY
];
390 /* Check arguments */
391 if ( (stride
< 0) || (size
!= 3) ) {
392 __glXSetError(gc
, GL_INVALID_VALUE
);
396 /* Choose appropriate api proc */
398 __GL_SEC_COLOR_FUNC(BYTE
, b
);
399 __GL_SEC_COLOR_FUNC(UNSIGNED_BYTE
, ub
);
400 __GL_SEC_COLOR_FUNC(SHORT
, s
);
401 __GL_SEC_COLOR_FUNC(UNSIGNED_SHORT
, us
);
402 __GL_SEC_COLOR_FUNC(INT
, i
);
403 __GL_SEC_COLOR_FUNC(UNSIGNED_INT
, ui
);
404 __GL_SEC_COLOR_FUNC(FLOAT
, f
);
405 __GL_SEC_COLOR_FUNC(DOUBLE
, d
);
407 __glXSetError(gc
, GL_INVALID_ENUM
);
411 seccolorPointer
->size
= size
;
412 seccolorPointer
->type
= type
;
413 seccolorPointer
->stride
= stride
;
414 seccolorPointer
->ptr
= pointer
;
416 /* Set internal state */
418 seccolorPointer
->skip
= size
* __glXTypeSize(type
);
420 seccolorPointer
->skip
= stride
;
424 void __indirect_glFogCoordPointerEXT(GLenum type
, GLsizei stride
, const GLvoid
* pointer
)
426 __GLXcontext
*gc
= __glXGetCurrentContext();
427 __GLXattribute
* state
= (__GLXattribute
*)(gc
->client_state_private
);
428 __GLXvertexArrayPointerState
*fogPointer
= &state
->vertArray
.arrays
[ fogCoord_ARRAY
];
430 /* Check arguments */
432 __glXSetError(gc
, GL_INVALID_VALUE
);
436 /* Choose appropriate api proc */
438 __GL_FOG_FUNC(FLOAT
, f
);
439 __GL_FOG_FUNC(DOUBLE
, d
);
441 __glXSetError(gc
, GL_INVALID_ENUM
);
445 fogPointer
->size
= 1;
446 fogPointer
->type
= type
;
447 fogPointer
->stride
= stride
;
448 fogPointer
->ptr
= pointer
;
450 /* Set internal state */
452 fogPointer
->skip
= __glXTypeSize(type
);
454 fogPointer
->skip
= stride
;
458 void __indirect_glInterleavedArrays(GLenum format
, GLsizei stride
, const GLvoid
*pointer
)
460 __GLXcontext
*gc
= __glXGetCurrentContext();
461 __GLXattribute
* state
= (__GLXattribute
*)(gc
->client_state_private
);
462 GLboolean tEnable
= GL_FALSE
, cEnable
= GL_FALSE
, nEnable
= GL_FALSE
;
463 GLenum tType
= GL_FLOAT
, nType
= GL_FLOAT
, vType
= GL_FLOAT
;
464 GLenum cType
= GL_FALSE
;
465 GLint tSize
= 0, cSize
= 0, nSize
= 3, vSize
;
466 int cOffset
= 0, nOffset
= 0, vOffset
= 0;
467 GLint trueStride
, size
;
472 size
= __glXTypeSize(vType
) * vSize
;
476 size
= __glXTypeSize(vType
) * vSize
;
481 cType
= GL_UNSIGNED_BYTE
;
483 vOffset
= __glXTypeSize(cType
) * cSize
;
484 size
= vOffset
+ __glXTypeSize(vType
) * vSize
;
489 cType
= GL_UNSIGNED_BYTE
;
491 vOffset
= __glXTypeSize(vType
) * cSize
;
492 size
= vOffset
+ __glXTypeSize(vType
) * vSize
;
499 vOffset
= __glXTypeSize(cType
) * cSize
;
500 size
= vOffset
+ __glXTypeSize(vType
) * vSize
;
505 vOffset
= __glXTypeSize(nType
) * nSize
;
506 size
= vOffset
+ __glXTypeSize(vType
) * vSize
;
513 nOffset
= __glXTypeSize(cType
) * cSize
;
515 vOffset
= nOffset
+ __glXTypeSize(nType
) * nSize
;
516 size
= vOffset
+ __glXTypeSize(vType
) * vSize
;
522 vOffset
= __glXTypeSize(tType
) * tSize
;
523 size
= vOffset
+ __glXTypeSize(vType
) * vSize
;
529 vOffset
= __glXTypeSize(tType
) * tSize
;
530 size
= vOffset
+ __glXTypeSize(vType
) * vSize
;
532 case GL_T2F_C4UB_V3F
:
537 cType
= GL_UNSIGNED_BYTE
;
538 cOffset
= __glXTypeSize(tType
) * tSize
;
540 vOffset
= cOffset
+ __glXTypeSize(cType
) * cSize
;
541 size
= vOffset
+ __glXTypeSize(vType
) * vSize
;
549 cOffset
= __glXTypeSize(tType
) * tSize
;
551 vOffset
= cOffset
+ __glXTypeSize(cType
) * cSize
;
552 size
= vOffset
+ __glXTypeSize(vType
) * vSize
;
558 nOffset
= __glXTypeSize(tType
) * tSize
;
560 vOffset
= nOffset
+ __glXTypeSize(nType
) * nSize
;
561 size
= vOffset
+ __glXTypeSize(vType
) * vSize
;
563 case GL_T2F_C4F_N3F_V3F
:
569 cOffset
= __glXTypeSize(tType
) * tSize
;
571 nOffset
= cOffset
+ __glXTypeSize(cType
) * cSize
;
573 vOffset
= nOffset
+ __glXTypeSize(nType
) * nSize
;
574 size
= vOffset
+ __glXTypeSize(vType
) * vSize
;
576 case GL_T4F_C4F_N3F_V4F
:
582 cOffset
= __glXTypeSize(tType
) * tSize
;
584 nOffset
= cOffset
+ __glXTypeSize(cType
) * cSize
;
586 vOffset
= nOffset
+ __glXTypeSize(nType
) * nSize
;
587 size
= vOffset
+ __glXTypeSize(vType
) * vSize
;
590 __glXSetError(gc
, GL_INVALID_ENUM
);
594 trueStride
= (stride
== 0) ? size
: stride
;
596 state
->vertArray
.enables
= 0;
597 state
->vertArray
.texture_enables
= 0;
599 __indirect_glEnableClientState(GL_TEXTURE_COORD_ARRAY
);
600 __indirect_glTexCoordPointer(tSize
, tType
, trueStride
, (const char *)pointer
);
603 __indirect_glEnableClientState(GL_COLOR_ARRAY
);
604 __indirect_glColorPointer(cSize
, cType
, trueStride
, (const char *)pointer
+cOffset
);
607 __indirect_glEnableClientState(GL_NORMAL_ARRAY
);
608 __indirect_glNormalPointer(nType
, trueStride
, (const char *)pointer
+nOffset
);
610 __indirect_glEnableClientState(GL_VERTEX_ARRAY
);
611 __indirect_glVertexPointer(vSize
, vType
, trueStride
, (const char *)pointer
+vOffset
);
614 /*****************************************************************************/
616 void __indirect_glArrayElement(GLint i
)
618 __GLXcontext
*gc
= __glXGetCurrentContext();
619 __GLXattribute
* state
= (__GLXattribute
*)(gc
->client_state_private
);
620 __GLXvertArrayState
*va
= &state
->vertArray
;
624 if (IS_TEXARRAY_ENABLED(state
, 0)) {
625 (*va
->texCoord
[0].proc
)(va
->texCoord
[0].ptr
+i
*va
->texCoord
[0].skip
);
628 /* Multitexturing is handled specially because the protocol
629 * requires an extra parameter.
631 for (j
=1; j
<__GLX_MAX_TEXTURE_UNITS
; ++j
) {
632 if (IS_TEXARRAY_ENABLED(state
, j
)) {
633 (*va
->texCoord
[j
].mtex_proc
)(GL_TEXTURE0
+ j
, va
->texCoord
[j
].ptr
+i
*va
->texCoord
[j
].skip
);
637 for ( j
= 0 ; j
< __GLX_MAX_ARRAYS
; j
++ ) {
638 if (IS_ARRAY_ENABLED_BY_INDEX(state
, j
)) {
639 (*va
->arrays
[ j
].proc
)(va
->arrays
[ j
].ptr
+i
*va
->arrays
[ j
].skip
);
646 __GLXdispatchDrawArraysComponentHeader ai
;
654 * Initialize a \c array_info structure for each array that is enabled in
655 * \c state. Determine how many arrays are enabled, and store the result
656 * in \c num_arrays. Determine how big each vertex is, and store the result
657 * in \c total_vertex_size.
659 * \returns The size of the final request. This is the size, in bytes, of
660 * the DrawArrays header, the ARRAY_INFO structures, and all the vertex data.
661 * This value \b assumes a \c X_GLXRender command is used. The true size
662 * will be 4 bytes larger if a \c X_GLXRenderLarge command is used.
665 prep_arrays(const __GLXattribute
* const state
, struct array_info
* arrays
,
667 GLsizei
*num_arrays
, GLsizei
*total_vertex_size
)
672 #define ASSIGN_ARRAY_INFO(state, enum_name, arr) \
674 arrays[ na ].ai.datatype = state->vertArray. arr .type ; \
675 arrays[ na ].ai.numVals = state->vertArray. arr .size ; \
676 arrays[ na ].ai.component = GL_ ## enum_name ## _ARRAY; \
678 arrays[ na ].bytes = state->vertArray. arr .size \
679 * __glXTypeSize( state->vertArray. arr .type ); \
680 arrays[ na ].ptr = state->vertArray. arr .ptr; \
681 arrays[ na ].skip = state->vertArray. arr .skip; \
683 vs += __GLX_PAD(arrays[ na ].bytes); \
687 #define ADD_ARRAY_IF_ENABLED(state, enum_name, arr) \
688 do { if ( IS_ARRAY_ENABLED(state, arr) ) { \
689 ASSIGN_ARRAY_INFO(state, enum_name, arrays[ arr ## _ARRAY ] ); \
692 ADD_ARRAY_IF_ENABLED(state
, VERTEX
, vertex
);
693 ADD_ARRAY_IF_ENABLED(state
, NORMAL
, normal
);
694 ADD_ARRAY_IF_ENABLED(state
, COLOR
, color
);
695 ADD_ARRAY_IF_ENABLED(state
, SECONDARY_COLOR
, secondaryColor
);
696 ADD_ARRAY_IF_ENABLED(state
, FOG_COORD
, fogCoord
);
697 ADD_ARRAY_IF_ENABLED(state
, EDGE_FLAG
, edgeFlag
);
698 ADD_ARRAY_IF_ENABLED(state
, INDEX
, index
);
700 /* The standard DrawArrays protocol *only* supports a single array of
701 * texture coordinates.
703 if ( IS_TEXARRAY_ENABLED(state
, 0) ) {
704 ASSIGN_ARRAY_INFO(state
, TEXTURE_COORD
, texCoord
[0]);
708 *total_vertex_size
= vs
;
710 return __GLX_PAD((__GLX_COMPONENT_HDR_SIZE
* na
)
712 + __GLX_DRAWARRAYS_CMD_HDR_SIZE
);
717 * Emits the vertex data for the DrawArrays GLX protocol.
720 emit_vertex(GLubyte
* data
, const struct array_info
* arrays
,
721 GLsizei num_arrays
, GLint element
, GLsizei offset
)
725 for ( i
= 0 ; i
< num_arrays
; i
++ ) {
726 (void) memcpy( data
+ offset
,
727 arrays
[i
].ptr
+ (arrays
[i
].skip
* element
),
729 offset
+= __GLX_PAD(arrays
[i
].bytes
);
737 emit_header(GLubyte
* pc
, const struct array_info
* arrays
,
738 GLsizei num_arrays
, GLsizei count
, GLenum mode
)
740 __GLXdispatchDrawArraysComponentHeader
*arrayInfo
;
743 __GLX_PUT_LONG(0, count
);
744 __GLX_PUT_LONG(4, num_arrays
);
745 __GLX_PUT_LONG(8, mode
);
747 arrayInfo
= (__GLXdispatchDrawArraysComponentHeader
*)
748 (pc
+ __GLX_DRAWARRAYS_HDR_SIZE
);
751 /* Write the ARRAY_INFO data.
754 for ( i
= 0 ; i
< num_arrays
; i
++ ) {
755 arrayInfo
[i
] = arrays
[i
].ai
;
761 * Emit GLX DrawArrays protocol using a GLXRender packet.
764 emit_Render_DrawArrays(__GLXcontext
* gc
, const struct array_info
* arrays
,
765 GLsizei first
, GLsizei count
, GLsizei num_arrays
, GLenum mode
,
766 GLsizei cmdlen
, GLsizei total_vertex_size
)
768 GLubyte
* pc
= gc
->pc
;
772 __GLX_BEGIN_VARIABLE(X_GLrop_DrawArrays
, cmdlen
);
773 emit_header(pc
+ 4, arrays
, num_arrays
, count
, mode
);
776 /* Write the actual array data.
779 offset
= __GLX_DRAWARRAYS_CMD_HDR_SIZE
780 + (num_arrays
* __GLX_COMPONENT_HDR_SIZE
);
781 for ( i
= 0 ; i
< count
; i
++ ) {
782 offset
= emit_vertex(pc
, arrays
, num_arrays
, i
+ first
, offset
);
790 * Emit GLX DrawArrays protocol using a GLXRenderLarge packet.
793 emit_RenderLarge_DrawArrays(__GLXcontext
* gc
, const struct array_info
* arrays
,
794 GLsizei first
, GLsizei count
, GLsizei num_arrays
, GLenum mode
,
795 GLsizei cmdlen
, GLsizei total_vertex_size
)
797 GLubyte
* pc
= gc
->pc
;
803 GLsizei elements_per_request
;
806 /* Calculate the maximum amount of data can be stuffed into a single
807 * packet. sz_xGLXRenderReq is added because bufSize is the maximum
808 * packet size minus sz_xGLXRenderReq.
810 * The important value here is elements_per_request. This is the number
811 * of complete array elements that will fit in a single buffer. There
812 * may be some wasted space at the end of the buffer, but splitting
813 * elements across buffer boundries would be painful.
816 maxSize
= (gc
->bufSize
+ sz_xGLXRenderReq
) - sz_xGLXRenderLargeReq
;
818 elements_per_request
= maxSize
/ total_vertex_size
;
820 totalRequests
= ((count
+ (elements_per_request
- 1))
821 / elements_per_request
) + 1;
824 /* Fill in the header data and send it away.
827 __GLX_BEGIN_VARIABLE_LARGE(X_GLrop_DrawArrays
, cmdlen
+4);
828 emit_header(pc
+ 8, arrays
, num_arrays
, count
, mode
);
830 gc
->pc
= pc
+ (__GLX_DRAWARRAYS_CMD_HDR_SIZE
+ 4)
831 + (__GLX_COMPONENT_HDR_SIZE
* num_arrays
);
832 __glXSendLargeChunk(gc
, 1, totalRequests
, gc
->buf
, gc
->pc
- gc
->buf
);
835 /* Write the actual array data.
839 for ( i
= 0 ; i
< count
; i
++ ) {
840 if ( i
== elements_per_request
) {
841 __glXSendLargeChunk(gc
, requestNumber
, totalRequests
,
851 offset
= emit_vertex(gc
->buf
, arrays
, num_arrays
, i
+ first
, offset
);
854 /* If the buffer isn't empty, emit the last, partial request.
857 assert(requestNumber
== totalRequests
);
858 __glXSendLargeChunk(gc
, requestNumber
, totalRequests
, gc
->buf
, offset
);
866 * Emit DrawArrays protocol. This function acts as a switch betteen
867 * \c emit_Render_DrawArrays and \c emit_RenderLarge_DrawArrays depending
868 * on how much array data is to be sent.
871 emit_DrawArraysEXT(const __GLXattribute
* const state
,
872 GLint first
, GLsizei count
, GLenum mode
)
874 struct array_info arrays
[32];
876 GLsizei total_vertex_size
;
877 __GLXcontext
*gc
= __glXGetCurrentContext();
881 /* Determine how big the final request will be. This depends on a number
882 * of factors. It depends on how many array elemets there are (which is
883 * the passed-in 'count'), how many arrays are enabled, how many elements
884 * are in each array entry, and what the types are for each array.
887 cmdlen
= prep_arrays(state
, arrays
, count
, & num_arrays
,
888 & total_vertex_size
);
891 /* If the data payload and the protocol header is too large for a Render
892 * command, use a RenderLarge command.
894 if (cmdlen
> gc
->maxSmallRenderCommandSize
) {
895 emit_RenderLarge_DrawArrays(gc
, arrays
, first
, count
, num_arrays
,
896 mode
, cmdlen
, total_vertex_size
);
899 emit_Render_DrawArrays(gc
, arrays
, first
, count
, num_arrays
,
900 mode
, cmdlen
, total_vertex_size
);
906 * Emit a DrawArrays call using the old "protocol." This isn't really
907 * DrawArrays protocol at all. It just simulates DrawArrays by using
908 * immediate-mode vertex calls. Very, very slow for large arrays, but works
909 * with every GLX server.
912 emit_DrawArrays_old(const __GLXattribute
* const state
,
913 GLint first
, GLsizei count
, GLenum mode
)
915 const __GLXvertArrayState
*va
= &state
->vertArray
;
916 const GLubyte
*vaPtr
[__GLX_MAX_ARRAYS
];
917 const GLubyte
*tcaPtr
[__GLX_MAX_TEXTURE_UNITS
];
921 ** Set up pointers for quick array traversal.
924 (void) memset( vaPtr
, 0, sizeof(vaPtr
) );
925 (void) memset( tcaPtr
, 0, sizeof(tcaPtr
) );
927 for ( j
= 0 ; j
< __GLX_MAX_ARRAYS
; j
++ ) {
928 if (IS_ARRAY_ENABLED_BY_INDEX(state
, j
)) {
929 vaPtr
[ j
] = va
->arrays
[ j
].ptr
+ first
* va
->arrays
[ j
].skip
;
933 for ( j
= 0 ; j
< __GLX_MAX_TEXTURE_UNITS
; j
++ ) {
934 if (IS_TEXARRAY_ENABLED(state
, j
))
935 tcaPtr
[ j
] = va
->texCoord
[ j
].ptr
+ first
* va
->texCoord
[ j
].skip
;
938 __indirect_glBegin(mode
);
939 for (i
= 0; i
< count
; i
++) {
940 if (IS_TEXARRAY_ENABLED(state
, 0)) {
941 (*va
->texCoord
[0].proc
)(tcaPtr
[0]);
942 tcaPtr
[0] += va
->texCoord
[0].skip
;
945 /* Multitexturing is handled specially because the protocol
946 * requires an extra parameter.
948 for (j
=1; j
<__GLX_MAX_TEXTURE_UNITS
; ++j
) {
949 if (IS_TEXARRAY_ENABLED(state
, j
)) {
950 (*va
->texCoord
[j
].mtex_proc
)(GL_TEXTURE0
+ j
, tcaPtr
[j
]);
951 tcaPtr
[j
] += va
->texCoord
[j
].skip
;
955 for ( j
= 0 ; j
< __GLX_MAX_ARRAYS
; j
++ ) {
956 if (IS_ARRAY_ENABLED_BY_INDEX(state
, j
)) {
957 (*va
->arrays
[ j
].proc
)(vaPtr
[ j
]);
958 vaPtr
[ j
] += va
->arrays
[ j
].skip
;
967 * Validate that the \c mode and \c count parameters to \c glDrawArrays or
968 * \c glDrawElements are valid. If the arguments are not valid, then an
969 * error code is set in the GLX context.
971 * \returns \c GL_TRUE if the arguments are valide, \c GL_FALSE if they are
975 glx_validate_array_args(__GLXcontext
*gc
, GLenum mode
, GLsizei count
)
982 case GL_TRIANGLE_STRIP
:
983 case GL_TRIANGLE_FAN
:
990 __glXSetError(gc
, GL_INVALID_ENUM
);
995 __glXSetError(gc
, GL_INVALID_VALUE
);
1003 void __indirect_glDrawArrays(GLenum mode
, GLint first
, GLsizei count
)
1005 __GLXcontext
*gc
= __glXGetCurrentContext();
1006 const __GLXattribute
* state
=
1007 (const __GLXattribute
*)(gc
->client_state_private
);
1010 if ( ! glx_validate_array_args(gc
, mode
, count
) ) {
1014 /* The "true" DrawArrays protocol does not support generic attributes,
1015 * multiple vertex arrays, or multiple texture coordinate arrays.
1017 if ( state
->NoDrawArraysProtocol
1018 || (state
->vertArray
.texture_enables
> 1) ) {
1019 emit_DrawArrays_old(state
, first
, count
, mode
);
1022 emit_DrawArraysEXT(state
, first
, count
, mode
);
1028 * \todo Modify this to use the "true" DrawArrays protocol if possible. This
1029 * would probably require refactoring out parts of \c emit_DrawArraysEXT into
1030 * more general functions that could be used in either place.
1032 void __indirect_glDrawElements(GLenum mode
, GLsizei count
, GLenum type
,
1033 const GLvoid
*indices
)
1035 __GLXcontext
*gc
= __glXGetCurrentContext();
1036 __GLXattribute
* state
= (__GLXattribute
*)(gc
->client_state_private
);
1037 __GLXvertArrayState
*va
= &state
->vertArray
;
1038 const GLubyte
*iPtr1
= NULL
;
1039 const GLushort
*iPtr2
= NULL
;
1040 const GLuint
*iPtr3
= NULL
;
1041 GLint i
, j
, offset
= 0;
1043 if ( ! glx_validate_array_args(gc
, mode
, count
) ) {
1048 case GL_UNSIGNED_BYTE
:
1049 iPtr1
= (const GLubyte
*)indices
;
1051 case GL_UNSIGNED_SHORT
:
1052 iPtr2
= (const GLushort
*)indices
;
1054 case GL_UNSIGNED_INT
:
1055 iPtr3
= (const GLuint
*)indices
;
1058 __glXSetError(gc
, GL_INVALID_ENUM
);
1062 __indirect_glBegin(mode
);
1063 for (i
= 0; i
< count
; i
++) {
1065 case GL_UNSIGNED_BYTE
:
1066 offset
= (GLint
)(*iPtr1
++);
1068 case GL_UNSIGNED_SHORT
:
1069 offset
= (GLint
)(*iPtr2
++);
1071 case GL_UNSIGNED_INT
:
1072 offset
= (GLint
)(*iPtr3
++);
1076 if (IS_TEXARRAY_ENABLED(state
, 0)) {
1077 (*va
->texCoord
[0].proc
)(va
->texCoord
[0].ptr
+
1078 (offset
*va
->texCoord
[0].skip
));
1081 /* Multitexturing is handled specially because the protocol
1082 * requires an extra parameter.
1084 for (j
=1; j
<__GLX_MAX_TEXTURE_UNITS
; ++j
) {
1085 if (IS_TEXARRAY_ENABLED(state
, j
)) {
1086 (*va
->texCoord
[j
].mtex_proc
)(GL_TEXTURE0
+ j
,
1087 va
->texCoord
[j
].ptr
+
1088 (offset
*va
->texCoord
[j
].skip
));
1092 for ( j
= 0 ; j
< __GLX_MAX_ARRAYS
; j
++ ) {
1093 if (IS_ARRAY_ENABLED_BY_INDEX(state
, j
)) {
1094 (*va
->arrays
[ j
].proc
)(va
->arrays
[ j
].ptr
1095 +(offset
*va
->arrays
[ j
].skip
));
1102 void __indirect_glDrawRangeElements(GLenum mode
, GLuint start
, GLuint end
,
1103 GLsizei count
, GLenum type
,
1104 const GLvoid
*indices
)
1106 __GLXcontext
*gc
= __glXGetCurrentContext();
1109 __glXSetError(gc
, GL_INVALID_VALUE
);
1113 __indirect_glDrawElements(mode
,count
,type
,indices
);
1116 void __indirect_glMultiDrawArraysEXT(GLenum mode
, GLint
*first
, GLsizei
*count
,
1121 for(i
=0; i
<primcount
; i
++) {
1122 if ( count
[i
] > 0 ) {
1123 __indirect_glDrawArrays( mode
, first
[i
], count
[i
] );
1128 void __indirect_glMultiDrawElementsEXT(GLenum mode
, const GLsizei
*count
,
1129 GLenum type
, const GLvoid
** indices
,
1134 for(i
=0; i
<primcount
; i
++) {
1135 if ( count
[i
] > 0 ) {
1136 __indirect_glDrawElements( mode
, count
[i
], type
, indices
[i
] );
1141 void __indirect_glClientActiveTextureARB(GLenum texture
)
1143 __GLXcontext
*gc
= __glXGetCurrentContext();
1144 __GLXattribute
* state
= (__GLXattribute
*)(gc
->client_state_private
);
1145 GLint unit
= (GLint
) texture
- GL_TEXTURE0
;
1147 if (unit
< 0 || __GLX_MAX_TEXTURE_UNITS
<= unit
) {
1148 __glXSetError(gc
, GL_INVALID_ENUM
);
1151 state
->vertArray
.activeTexture
= unit
;