Added a bunch of extensions that were previously supported but weren't
[mesa.git] / src / glx / x11 / vertarr.c
1 /* $XFree86: xc/lib/GL/glx/vertarr.c,v 1.4 2001/03/25 05:32:00 tsi Exp $ */
2 /*
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:
10 **
11 ** http://oss.sgi.com/projects/FreeB
12 **
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.
18 **
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.
24 **
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.
34 **
35 */
36
37 #include <assert.h>
38 #include "glxclient.h"
39 #include "packrender.h"
40 #include "indirect.h"
41 #include <string.h>
42 #include <limits.h> /* INT_MAX */
43
44 /* macros for setting function pointers */
45 #define __GL_VERTEX_FUNC(NAME, let) \
46 case GL_##NAME: \
47 if (size == 2) \
48 vertexPointer->proc = (void (*)(const void *))__indirect_glVertex2##let##v; \
49 else if (size == 3) \
50 vertexPointer->proc = (void (*)(const void *))__indirect_glVertex3##let##v; \
51 else if (size == 4) \
52 vertexPointer->proc = (void (*)(const void *))__indirect_glVertex4##let##v; \
53 break
54
55 #define __GL_NORMAL_FUNC(NAME, let) \
56 case GL_##NAME: \
57 normalPointer->proc = (void (*)(const void *))__indirect_glNormal3##let##v; \
58 break
59
60 #define __GL_COLOR_FUNC(NAME, let) \
61 case GL_##NAME: \
62 if (size == 3) \
63 colorPointer->proc = (void (*)(const void *))__indirect_glColor3##let##v; \
64 else if (size == 4)\
65 colorPointer->proc = (void (*)(const void *))__indirect_glColor4##let##v; \
66 break
67
68 #define __GL_SEC_COLOR_FUNC(NAME, let) \
69 case GL_##NAME: \
70 seccolorPointer->proc = (void (*)(const void *))__indirect_glSecondaryColor3##let##vEXT; \
71
72 #define __GL_FOG_FUNC(NAME, let) \
73 case GL_##NAME: \
74 fogPointer->proc = (void (*)(const void *))__indirect_glFogCoord##let##vEXT; \
75
76 #define __GL_INDEX_FUNC(NAME, let) \
77 case GL_##NAME: \
78 indexPointer->proc = (void (*)(const void *))__indirect_glIndex##let##v; \
79 break
80
81 #define __GL_TEXTURE_FUNC(NAME, let) \
82 case GL_##NAME: \
83 if (size == 1) { \
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; \
95 } break
96
97 /**
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.
102 *
103 * \notes
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.
106 */
107 static const GLuint __glXTypeSize_table[16] = {
108 1, 1, 2, 2, 4, 4, 4, 0, 0, 0, 8, 0, 0, 0, 0, 0
109 };
110
111 #define __glXTypeSize(e) ((((e) & ~0x0f) != 0x1400) \
112 ? 0 : __glXTypeSize_table[ (e) & 0x0f ])
113
114
115 /**
116 * Initialize vertex array state for a GLX context.
117 *
118 * \param gc GLX context whose vertex array state is to be initialized.
119 *
120 * \todo
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,
126 * however.
127 */
128 void __glXInitVertexArrayState(__GLXcontext *gc)
129 {
130 __GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
131 __GLXvertArrayState *va = &state->vertArray;
132 GLint i;
133
134 va->enables = 0;
135 va->texture_enables = 0;
136
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;
144 }
145
146 va->arrays[ edgeFlag_ARRAY ].type = GL_UNSIGNED_BYTE;;
147
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;
152
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;
160 }
161
162 va->maxElementsVertices = INT_MAX;
163 va->maxElementsIndices = INT_MAX;
164 }
165
166 /*****************************************************************************/
167
168 /**
169 * \name Vertex array pointer bridge functions
170 *
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
175 * happen.
176 */
177 /*@{*/
178 void __indirect_glColorPointerEXT(GLint size, GLenum type, GLsizei stride,
179 GLsizei count, const GLvoid * pointer )
180 {
181 (void) count; __indirect_glColorPointer( size, type, stride, pointer );
182 }
183
184 void __indirect_glEdgeFlagPointerEXT(GLsizei stride,
185 GLsizei count, const GLboolean * pointer )
186 {
187 (void) count; __indirect_glEdgeFlagPointer( stride, pointer );
188 }
189
190 void __indirect_glIndexPointerEXT(GLenum type, GLsizei stride,
191 GLsizei count, const GLvoid * pointer )
192 {
193 (void) count; __indirect_glIndexPointer( type, stride, pointer );
194 }
195
196 void __indirect_glNormalPointerEXT(GLenum type, GLsizei stride, GLsizei count,
197 const GLvoid * pointer )
198 {
199 (void) count; __indirect_glNormalPointer( type, stride, pointer );
200 }
201
202 void __indirect_glTexCoordPointerEXT(GLint size, GLenum type, GLsizei stride,
203 GLsizei count, const GLvoid * pointer )
204 {
205 (void) count; __indirect_glTexCoordPointer( size, type, stride, pointer );
206 }
207
208 void __indirect_glVertexPointerEXT(GLint size, GLenum type, GLsizei stride,
209 GLsizei count, const GLvoid * pointer )
210 {
211 (void) count; __indirect_glVertexPointer( size, type, stride, pointer );
212 }
213 /*@}*/
214
215 /*****************************************************************************/
216
217 void __indirect_glVertexPointer(GLint size, GLenum type, GLsizei stride,
218 const GLvoid *pointer)
219 {
220 __GLXcontext *gc = __glXGetCurrentContext();
221 __GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
222 __GLXvertexArrayPointerState *vertexPointer = &state->vertArray.arrays[ vertex_ARRAY ];
223
224 /* Check arguments */
225 if (size < 2 || size > 4 || stride < 0) {
226 __glXSetError(gc, GL_INVALID_VALUE);
227 return;
228 }
229
230 /* Choose appropriate api proc */
231 switch(type) {
232 __GL_VERTEX_FUNC(SHORT, s);
233 __GL_VERTEX_FUNC(INT, i);
234 __GL_VERTEX_FUNC(FLOAT, f);
235 __GL_VERTEX_FUNC(DOUBLE, d);
236 default:
237 __glXSetError(gc, GL_INVALID_ENUM);
238 return;
239 }
240
241 vertexPointer->size = size;
242 vertexPointer->type = type;
243 vertexPointer->stride = stride;
244 vertexPointer->ptr = pointer;
245
246 /* Set internal state */
247 if (stride == 0) {
248 vertexPointer->skip = __glXTypeSize(type) * size;
249 } else {
250 vertexPointer->skip = stride;
251 }
252 }
253
254 void __indirect_glNormalPointer(GLenum type, GLsizei stride, const GLvoid *pointer)
255 {
256 __GLXcontext *gc = __glXGetCurrentContext();
257 __GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
258 __GLXvertexArrayPointerState *normalPointer = &state->vertArray.arrays[ normal_ARRAY ];
259
260 /* Check arguments */
261 if (stride < 0) {
262 __glXSetError(gc, GL_INVALID_VALUE);
263 return;
264 }
265
266 /* Choose appropriate api proc */
267 switch(type) {
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);
273 default:
274 __glXSetError(gc, GL_INVALID_ENUM);
275 return;
276 }
277
278 normalPointer->type = type;
279 normalPointer->stride = stride;
280 normalPointer->ptr = pointer;
281
282 /* Set internal state */
283 if (stride == 0) {
284 normalPointer->skip = 3 * __glXTypeSize(type);
285 } else {
286 normalPointer->skip = stride;
287 }
288 }
289
290 void __indirect_glColorPointer(GLint size, GLenum type, GLsizei stride,
291 const GLvoid *pointer)
292 {
293 __GLXcontext *gc = __glXGetCurrentContext();
294 __GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
295 __GLXvertexArrayPointerState *colorPointer = &state->vertArray.arrays[ color_ARRAY ];
296
297 /* Check arguments */
298 if (stride < 0) {
299 __glXSetError(gc, GL_INVALID_VALUE);
300 return;
301 }
302
303 /* Choose appropriate api proc */
304 switch(type) {
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);
313 default:
314 __glXSetError(gc, GL_INVALID_ENUM);
315 return;
316 }
317
318 colorPointer->size = size;
319 colorPointer->type = type;
320 colorPointer->stride = stride;
321 colorPointer->ptr = pointer;
322
323 /* Set internal state */
324 if (stride == 0) {
325 colorPointer->skip = size * __glXTypeSize(type);
326 } else {
327 colorPointer->skip = stride;
328 }
329 }
330
331 void __indirect_glIndexPointer(GLenum type, GLsizei stride, const GLvoid *pointer)
332 {
333 __GLXcontext *gc = __glXGetCurrentContext();
334 __GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
335 __GLXvertexArrayPointerState *indexPointer = &state->vertArray.arrays[ index_ARRAY ];
336
337 /* Check arguments */
338 if (stride < 0) {
339 __glXSetError(gc, GL_INVALID_VALUE);
340 return;
341 }
342
343 /* Choose appropriate api proc */
344 switch(type) {
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);
350 default:
351 __glXSetError(gc, GL_INVALID_ENUM);
352 return;
353 }
354
355 indexPointer->type = type;
356 indexPointer->stride = stride;
357 indexPointer->ptr = pointer;
358
359 /* Set internal state */
360 if (stride == 0) {
361 indexPointer->skip = __glXTypeSize(type);
362 } else {
363 indexPointer->skip = stride;
364 }
365 }
366
367 void __indirect_glTexCoordPointer(GLint size, GLenum type, GLsizei stride,
368 const GLvoid *pointer)
369 {
370 __GLXcontext *gc = __glXGetCurrentContext();
371 __GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
372 __GLXvertexArrayPointerState *texCoordPointer =
373 &state->vertArray.texCoord[state->vertArray.activeTexture];
374
375 /* Check arguments */
376 if (size < 1 || size > 4 || stride < 0) {
377 __glXSetError(gc, GL_INVALID_VALUE);
378 return;
379 }
380
381 /* Choose appropriate api proc */
382 switch(type) {
383 __GL_TEXTURE_FUNC(SHORT, s);
384 __GL_TEXTURE_FUNC(INT, i);
385 __GL_TEXTURE_FUNC(FLOAT, f);
386 __GL_TEXTURE_FUNC(DOUBLE, d);
387 default:
388 __glXSetError(gc, GL_INVALID_ENUM);
389 return;
390 }
391
392 texCoordPointer->size = size;
393 texCoordPointer->type = type;
394 texCoordPointer->stride = stride;
395 texCoordPointer->ptr = pointer;
396
397 /* Set internal state */
398 if (stride == 0) {
399 texCoordPointer->skip = __glXTypeSize(type) * size;
400 } else {
401 texCoordPointer->skip = stride;
402 }
403 }
404
405 void __indirect_glEdgeFlagPointer(GLsizei stride, const GLvoid *pointer)
406 {
407 __GLXcontext *gc = __glXGetCurrentContext();
408 __GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
409 __GLXvertexArrayPointerState *edgeFlagPointer = &state->vertArray.arrays[ edgeFlag_ARRAY ];
410
411 /* Check arguments */
412 if (stride < 0) {
413 __glXSetError(gc, GL_INVALID_VALUE);
414 return;
415 }
416
417 /* Choose appropriate api proc */
418 edgeFlagPointer->proc = (void (*)(const void *))__indirect_glEdgeFlagv;
419
420 edgeFlagPointer->stride = stride;
421 edgeFlagPointer->ptr = pointer;
422
423 /* Set internal state */
424 if (stride == 0) {
425 edgeFlagPointer->skip = sizeof(GLboolean);
426 } else {
427 edgeFlagPointer->skip = stride;
428 }
429
430 }
431
432 void __indirect_glSecondaryColorPointerEXT(GLint size, GLenum type, GLsizei stride,
433 const GLvoid * pointer )
434 {
435 __GLXcontext *gc = __glXGetCurrentContext();
436 __GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
437 __GLXvertexArrayPointerState *seccolorPointer = &state->vertArray.arrays[ secondaryColor_ARRAY ];
438
439 /* Check arguments */
440 if ( (stride < 0) || (size != 3) ) {
441 __glXSetError(gc, GL_INVALID_VALUE);
442 return;
443 }
444
445 /* Choose appropriate api proc */
446 switch(type) {
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);
455 default:
456 __glXSetError(gc, GL_INVALID_ENUM);
457 return;
458 }
459
460 seccolorPointer->size = size;
461 seccolorPointer->type = type;
462 seccolorPointer->stride = stride;
463 seccolorPointer->ptr = pointer;
464
465 /* Set internal state */
466 if (stride == 0) {
467 seccolorPointer->skip = size * __glXTypeSize(type);
468 } else {
469 seccolorPointer->skip = stride;
470 }
471 }
472
473 void __indirect_glFogCoordPointerEXT(GLenum type, GLsizei stride, const GLvoid * pointer)
474 {
475 __GLXcontext *gc = __glXGetCurrentContext();
476 __GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
477 __GLXvertexArrayPointerState *fogPointer = &state->vertArray.arrays[ fogCoord_ARRAY ];
478
479 /* Check arguments */
480 if (stride < 0) {
481 __glXSetError(gc, GL_INVALID_VALUE);
482 return;
483 }
484
485 /* Choose appropriate api proc */
486 switch(type) {
487 __GL_FOG_FUNC(FLOAT, f);
488 __GL_FOG_FUNC(DOUBLE, d);
489 default:
490 __glXSetError(gc, GL_INVALID_ENUM);
491 return;
492 }
493
494 fogPointer->size = 1;
495 fogPointer->type = type;
496 fogPointer->stride = stride;
497 fogPointer->ptr = pointer;
498
499 /* Set internal state */
500 if (stride == 0) {
501 fogPointer->skip = __glXTypeSize(type);
502 } else {
503 fogPointer->skip = stride;
504 }
505 }
506
507 void __indirect_glInterleavedArrays(GLenum format, GLsizei stride, const GLvoid *pointer)
508 {
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;
517
518 switch (format) {
519 case GL_V2F:
520 vSize = 2;
521 size = __glXTypeSize(vType) * vSize;
522 break;
523 case GL_V3F:
524 vSize = 3;
525 size = __glXTypeSize(vType) * vSize;
526 break;
527 case GL_C4UB_V2F:
528 cEnable = GL_TRUE;
529 cSize = 4;
530 cType = GL_UNSIGNED_BYTE;
531 vSize = 2;
532 vOffset = __glXTypeSize(cType) * cSize;
533 size = vOffset + __glXTypeSize(vType) * vSize;
534 break;
535 case GL_C4UB_V3F:
536 cEnable = GL_TRUE;
537 cSize = 4;
538 cType = GL_UNSIGNED_BYTE;
539 vSize = 3;
540 vOffset = __glXTypeSize(vType) * cSize;
541 size = vOffset + __glXTypeSize(vType) * vSize;
542 break;
543 case GL_C3F_V3F:
544 cEnable = GL_TRUE;
545 cSize = 3;
546 cType = GL_FLOAT;
547 vSize = 3;
548 vOffset = __glXTypeSize(cType) * cSize;
549 size = vOffset + __glXTypeSize(vType) * vSize;
550 break;
551 case GL_N3F_V3F:
552 nEnable = GL_TRUE;
553 vSize = 3;
554 vOffset = __glXTypeSize(nType) * nSize;
555 size = vOffset + __glXTypeSize(vType) * vSize;
556 break;
557 case GL_C4F_N3F_V3F:
558 cEnable = GL_TRUE;
559 cSize = 4;
560 cType = GL_FLOAT;
561 nEnable = GL_TRUE;
562 nOffset = __glXTypeSize(cType) * cSize;
563 vSize = 3;
564 vOffset = nOffset + __glXTypeSize(nType) * nSize;
565 size = vOffset + __glXTypeSize(vType) * vSize;
566 break;
567 case GL_T2F_V3F:
568 tEnable = GL_TRUE;
569 tSize = 2;
570 vSize = 3;
571 vOffset = __glXTypeSize(tType) * tSize;
572 size = vOffset + __glXTypeSize(vType) * vSize;
573 break;
574 case GL_T4F_V4F:
575 tEnable = GL_TRUE;
576 tSize = 4;
577 vSize = 4;
578 vOffset = __glXTypeSize(tType) * tSize;
579 size = vOffset + __glXTypeSize(vType) * vSize;
580 break;
581 case GL_T2F_C4UB_V3F:
582 tEnable = GL_TRUE;
583 tSize = 2;
584 cEnable = GL_TRUE;
585 cSize = 4;
586 cType = GL_UNSIGNED_BYTE;
587 cOffset = __glXTypeSize(tType) * tSize;
588 vSize = 3;
589 vOffset = cOffset + __glXTypeSize(cType) * cSize;
590 size = vOffset + __glXTypeSize(vType) * vSize;
591 break;
592 case GL_T2F_C3F_V3F:
593 tEnable = GL_TRUE;
594 tSize = 2;
595 cEnable = GL_TRUE;
596 cSize = 3;
597 cType = GL_FLOAT;
598 cOffset = __glXTypeSize(tType) * tSize;
599 vSize = 3;
600 vOffset = cOffset + __glXTypeSize(cType) * cSize;
601 size = vOffset + __glXTypeSize(vType) * vSize;
602 break;
603 case GL_T2F_N3F_V3F:
604 tEnable = GL_TRUE;
605 tSize = 2;
606 nEnable = GL_TRUE;
607 nOffset = __glXTypeSize(tType) * tSize;
608 vSize = 3;
609 vOffset = nOffset + __glXTypeSize(nType) * nSize;
610 size = vOffset + __glXTypeSize(vType) * vSize;
611 break;
612 case GL_T2F_C4F_N3F_V3F:
613 tEnable = GL_TRUE;
614 tSize = 2;
615 cEnable = GL_TRUE;
616 cSize = 4;
617 cType = GL_FLOAT;
618 cOffset = __glXTypeSize(tType) * tSize;
619 nEnable = GL_TRUE;
620 nOffset = cOffset + __glXTypeSize(cType) * cSize;
621 vSize = 3;
622 vOffset = nOffset + __glXTypeSize(nType) * nSize;
623 size = vOffset + __glXTypeSize(vType) * vSize;
624 break;
625 case GL_T4F_C4F_N3F_V4F:
626 tEnable = GL_TRUE;
627 tSize = 4;
628 cEnable = GL_TRUE;
629 cSize = 4;
630 cType = GL_FLOAT;
631 cOffset = __glXTypeSize(tType) * tSize;
632 nEnable = GL_TRUE;
633 nOffset = cOffset + __glXTypeSize(cType) * cSize;
634 vSize = 4;
635 vOffset = nOffset + __glXTypeSize(nType) * nSize;
636 size = vOffset + __glXTypeSize(vType) * vSize;
637 break;
638 default:
639 __glXSetError(gc, GL_INVALID_ENUM);
640 return;
641 }
642
643 trueStride = (stride == 0) ? size : stride;
644
645 state->vertArray.enables = 0;
646 state->vertArray.texture_enables = 0;
647 if (tEnable) {
648 __indirect_glEnableClientState(GL_TEXTURE_COORD_ARRAY);
649 __indirect_glTexCoordPointer(tSize, tType, trueStride, (const char *)pointer);
650 }
651 if (cEnable) {
652 __indirect_glEnableClientState(GL_COLOR_ARRAY);
653 __indirect_glColorPointer(cSize, cType, trueStride, (const char *)pointer+cOffset);
654 }
655 if (nEnable) {
656 __indirect_glEnableClientState(GL_NORMAL_ARRAY);
657 __indirect_glNormalPointer(nType, trueStride, (const char *)pointer+nOffset);
658 }
659 __indirect_glEnableClientState(GL_VERTEX_ARRAY);
660 __indirect_glVertexPointer(vSize, vType, trueStride, (const char *)pointer+vOffset);
661 }
662
663 /*****************************************************************************/
664
665 void __indirect_glArrayElement(GLint i)
666 {
667 __GLXcontext *gc = __glXGetCurrentContext();
668 __GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
669 __GLXvertArrayState *va = &state->vertArray;
670 GLint j;
671
672
673 if (IS_TEXARRAY_ENABLED(state, 0)) {
674 (*va->texCoord[0].proc)(va->texCoord[0].ptr+i*va->texCoord[0].skip);
675 }
676
677 /* Multitexturing is handled specially because the protocol
678 * requires an extra parameter.
679 */
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);
683 }
684 }
685
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);
689 }
690 }
691 }
692
693
694 struct array_info {
695 __GLXdispatchDrawArraysComponentHeader ai;
696 GLsizei bytes;
697 const GLubyte *ptr;
698 GLsizei skip;
699 };
700
701
702 /**
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.
707 *
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.
712 */
713 static GLuint
714 prep_arrays(const __GLXattribute * const state, struct array_info * arrays,
715 GLint count,
716 GLsizei *num_arrays, GLsizei *total_vertex_size)
717 {
718 GLsizei na = 0;
719 GLsizei vs = 0;
720
721 #define ASSIGN_ARRAY_INFO(state, enum_name, arr) \
722 do { \
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; \
726 \
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; \
731 \
732 vs += __GLX_PAD(arrays[ na ].bytes); \
733 na++; \
734 } while( 0 )
735
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 ] ); \
739 } } while( 0 )
740
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);
748
749 /* The standard DrawArrays protocol *only* supports a single array of
750 * texture coordinates.
751 */
752 if ( IS_TEXARRAY_ENABLED(state, 0) ) {
753 ASSIGN_ARRAY_INFO(state, TEXTURE_COORD, texCoord[0]);
754 }
755
756 *num_arrays = na;
757 *total_vertex_size = vs;
758
759 return __GLX_PAD((__GLX_COMPONENT_HDR_SIZE * na)
760 + (vs * count)
761 + __GLX_DRAWARRAYS_CMD_HDR_SIZE);
762 }
763
764
765 /**
766 * Emits the vertex data for the DrawArrays GLX protocol.
767 */
768 static GLsizei
769 emit_vertex(GLubyte * data, const struct array_info * arrays,
770 GLsizei num_arrays, GLint element, GLsizei offset)
771 {
772 GLint i;
773
774 for ( i = 0 ; i < num_arrays ; i++ ) {
775 (void) memcpy( data + offset,
776 arrays[i].ptr + (arrays[i].skip * element),
777 arrays[i].bytes );
778 offset += __GLX_PAD(arrays[i].bytes);
779 }
780
781 return offset;
782 }
783
784
785 static void
786 emit_header(GLubyte * pc, const struct array_info * arrays,
787 GLsizei num_arrays, GLsizei count, GLenum mode)
788 {
789 __GLXdispatchDrawArraysComponentHeader *arrayInfo;
790 GLsizei i;
791
792 __GLX_PUT_LONG(0, count);
793 __GLX_PUT_LONG(4, num_arrays);
794 __GLX_PUT_LONG(8, mode);
795
796 arrayInfo = (__GLXdispatchDrawArraysComponentHeader *)
797 (pc + __GLX_DRAWARRAYS_HDR_SIZE);
798
799
800 /* Write the ARRAY_INFO data.
801 */
802
803 for ( i = 0 ; i < num_arrays ; i++ ) {
804 arrayInfo[i] = arrays[i].ai;
805 }
806 }
807
808
809 /**
810 * Emit GLX DrawArrays protocol using a GLXRender packet.
811 */
812 static void
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)
816 {
817 GLubyte * pc = gc->pc;
818 GLsizei offset;
819 GLsizei i;
820
821 __GLX_BEGIN_VARIABLE(X_GLrop_DrawArrays, cmdlen);
822 emit_header(pc + 4, arrays, num_arrays, count, mode);
823
824
825 /* Write the actual array data.
826 */
827
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);
832 }
833
834 __GLX_END(cmdlen);
835 }
836
837
838 /**
839 * Emit GLX DrawArrays protocol using a GLXRenderLarge packet.
840 */
841 static void
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)
845 {
846 GLubyte * pc = gc->pc;
847 GLsizei offset;
848 GLsizei i;
849 GLint maxSize;
850 GLint totalRequests;
851 GLint requestNumber;
852 GLsizei elements_per_request;
853
854
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.
858 *
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.
863 */
864
865 maxSize = (gc->bufSize + sz_xGLXRenderReq) - sz_xGLXRenderLargeReq;
866
867 elements_per_request = maxSize / total_vertex_size;
868
869 totalRequests = ((count + (elements_per_request - 1))
870 / elements_per_request) + 1;
871
872
873 /* Fill in the header data and send it away.
874 */
875
876 __GLX_BEGIN_VARIABLE_LARGE(X_GLrop_DrawArrays, cmdlen+4);
877 emit_header(pc + 8, arrays, num_arrays, count, mode);
878
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);
882
883
884 /* Write the actual array data.
885 */
886 offset = 0;
887 requestNumber = 2;
888 for ( i = 0 ; i < count ; i++ ) {
889 if ( i == elements_per_request ) {
890 __glXSendLargeChunk(gc, requestNumber, totalRequests,
891 gc->buf, offset);
892 requestNumber++;
893 offset = 0;
894
895 count -= i;
896 first += i;
897 i = 0;
898 }
899
900 offset = emit_vertex(gc->buf, arrays, num_arrays, i + first, offset);
901 }
902
903 /* If the buffer isn't empty, emit the last, partial request.
904 */
905 if ( offset != 0 ) {
906 assert(requestNumber == totalRequests);
907 __glXSendLargeChunk(gc, requestNumber, totalRequests, gc->buf, offset);
908 }
909
910 gc->pc = gc->buf;
911 }
912
913
914 /**
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.
918 */
919 static void
920 emit_DrawArraysEXT(const __GLXattribute * const state,
921 GLint first, GLsizei count, GLenum mode)
922 {
923 struct array_info arrays[32];
924 GLsizei num_arrays;
925 GLsizei total_vertex_size;
926 __GLXcontext *gc = __glXGetCurrentContext();
927 GLuint cmdlen;
928
929
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.
934 */
935
936 cmdlen = prep_arrays(state, arrays, count, & num_arrays,
937 & total_vertex_size);
938
939
940 /* If the data payload and the protocol header is too large for a Render
941 * command, use a RenderLarge command.
942 */
943 if (cmdlen > gc->maxSmallRenderCommandSize) {
944 emit_RenderLarge_DrawArrays(gc, arrays, first, count, num_arrays,
945 mode, cmdlen, total_vertex_size);
946 }
947 else {
948 emit_Render_DrawArrays(gc, arrays, first, count, num_arrays,
949 mode, cmdlen, total_vertex_size);
950 }
951 }
952
953
954 /**
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.
959 */
960 static void
961 emit_DrawArrays_old(const __GLXattribute * const state,
962 GLint first, GLsizei count, GLenum mode)
963 {
964 const __GLXvertArrayState *va = &state->vertArray;
965 const GLubyte *vaPtr[__GLX_MAX_ARRAYS];
966 const GLubyte *tcaPtr[__GLX_MAX_TEXTURE_UNITS];
967 GLint i, j;
968
969 /*
970 ** Set up pointers for quick array traversal.
971 */
972
973 (void) memset( vaPtr, 0, sizeof(vaPtr) );
974 (void) memset( tcaPtr, 0, sizeof(tcaPtr) );
975
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;
979 }
980 }
981
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;
985 }
986
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;
992 }
993
994 /* Multitexturing is handled specially because the protocol
995 * requires an extra parameter.
996 */
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;
1001 }
1002 }
1003
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;
1008 }
1009 }
1010 }
1011 __indirect_glEnd();
1012 }
1013
1014
1015 /**
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.
1019 *
1020 * \returns \c GL_TRUE if the arguments are valide, \c GL_FALSE if they are
1021 * not.
1022 */
1023 static GLboolean
1024 glx_validate_array_args(__GLXcontext *gc, GLenum mode, GLsizei count)
1025 {
1026 switch(mode) {
1027 case GL_POINTS:
1028 case GL_LINE_STRIP:
1029 case GL_LINE_LOOP:
1030 case GL_LINES:
1031 case GL_TRIANGLE_STRIP:
1032 case GL_TRIANGLE_FAN:
1033 case GL_TRIANGLES:
1034 case GL_QUAD_STRIP:
1035 case GL_QUADS:
1036 case GL_POLYGON:
1037 break;
1038 default:
1039 __glXSetError(gc, GL_INVALID_ENUM);
1040 return GL_FALSE;
1041 }
1042
1043 if (count < 0) {
1044 __glXSetError(gc, GL_INVALID_VALUE);
1045 return GL_FALSE;
1046 }
1047
1048 return GL_TRUE;
1049 }
1050
1051
1052 void __indirect_glDrawArrays(GLenum mode, GLint first, GLsizei count)
1053 {
1054 __GLXcontext *gc = __glXGetCurrentContext();
1055 const __GLXattribute * state =
1056 (const __GLXattribute *)(gc->client_state_private);
1057
1058
1059 if ( ! glx_validate_array_args(gc, mode, count) ) {
1060 return;
1061 }
1062
1063 /* The "true" DrawArrays protocol does not support generic attributes,
1064 * multiple vertex arrays, or multiple texture coordinate arrays.
1065 */
1066 if ( state->NoDrawArraysProtocol
1067 || (state->vertArray.texture_enables > 1) ) {
1068 emit_DrawArrays_old(state, first, count, mode);
1069 }
1070 else {
1071 emit_DrawArraysEXT(state, first, count, mode);
1072 }
1073 }
1074
1075
1076 /**
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.
1080 */
1081 void __indirect_glDrawElements(GLenum mode, GLsizei count, GLenum type,
1082 const GLvoid *indices)
1083 {
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;
1091
1092 if ( ! glx_validate_array_args(gc, mode, count) ) {
1093 return;
1094 }
1095
1096 switch (type) {
1097 case GL_UNSIGNED_BYTE:
1098 iPtr1 = (const GLubyte *)indices;
1099 break;
1100 case GL_UNSIGNED_SHORT:
1101 iPtr2 = (const GLushort *)indices;
1102 break;
1103 case GL_UNSIGNED_INT:
1104 iPtr3 = (const GLuint *)indices;
1105 break;
1106 default:
1107 __glXSetError(gc, GL_INVALID_ENUM);
1108 return;
1109 }
1110
1111 __indirect_glBegin(mode);
1112 for (i = 0; i < count; i++) {
1113 switch (type) {
1114 case GL_UNSIGNED_BYTE:
1115 offset = (GLint)(*iPtr1++);
1116 break;
1117 case GL_UNSIGNED_SHORT:
1118 offset = (GLint)(*iPtr2++);
1119 break;
1120 case GL_UNSIGNED_INT:
1121 offset = (GLint)(*iPtr3++);
1122 break;
1123 }
1124
1125 if (IS_TEXARRAY_ENABLED(state, 0)) {
1126 (*va->texCoord[0].proc)(va->texCoord[0].ptr+
1127 (offset*va->texCoord[0].skip));
1128 }
1129
1130 /* Multitexturing is handled specially because the protocol
1131 * requires an extra parameter.
1132 */
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));
1138 }
1139 }
1140
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));
1145 }
1146 }
1147 }
1148 __indirect_glEnd();
1149 }
1150
1151 void __indirect_glDrawRangeElements(GLenum mode, GLuint start, GLuint end,
1152 GLsizei count, GLenum type,
1153 const GLvoid *indices)
1154 {
1155 __GLXcontext *gc = __glXGetCurrentContext();
1156
1157 if (end < start) {
1158 __glXSetError(gc, GL_INVALID_VALUE);
1159 return;
1160 }
1161
1162 __indirect_glDrawElements(mode,count,type,indices);
1163 }
1164
1165 void __indirect_glMultiDrawArraysEXT(GLenum mode, GLint *first, GLsizei *count,
1166 GLsizei primcount)
1167 {
1168 GLsizei i;
1169
1170 for(i=0; i<primcount; i++) {
1171 if ( count[i] > 0 ) {
1172 __indirect_glDrawArrays( mode, first[i], count[i] );
1173 }
1174 }
1175 }
1176
1177 void __indirect_glMultiDrawElementsEXT(GLenum mode, const GLsizei *count,
1178 GLenum type, const GLvoid ** indices,
1179 GLsizei primcount)
1180 {
1181 GLsizei i;
1182
1183 for(i=0; i<primcount; i++) {
1184 if ( count[i] > 0 ) {
1185 __indirect_glDrawElements( mode, count[i], type, indices[i] );
1186 }
1187 }
1188 }
1189
1190 void __indirect_glClientActiveTextureARB(GLenum texture)
1191 {
1192 __GLXcontext *gc = __glXGetCurrentContext();
1193 __GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
1194 GLint unit = (GLint) texture - GL_TEXTURE0;
1195
1196 if (unit < 0 || __GLX_MAX_TEXTURE_UNITS <= unit) {
1197 __glXSetError(gc, GL_INVALID_ENUM);
1198 return;
1199 }
1200 state->vertArray.activeTexture = unit;
1201 }