fix for (some of?) the vertex array problems
[mesa.git] / src / mesa / main / varray.c
1 /* $Id: varray.c,v 1.10 1999/11/09 09:18:40 keithw Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.1
6 *
7 * Copyright (C) 1999 Brian Paul All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27 #ifdef PC_HEADER
28 #include "all.h"
29 #else
30 #ifndef XFree86Server
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <string.h>
34 #else
35 #include "GL/xf86glx.h"
36 #endif
37 #include "context.h"
38 #include "api.h"
39 #include "cva.h"
40 #include "enable.h"
41 #include "enums.h"
42 #include "dlist.h"
43 #include "light.h"
44 #include "macros.h"
45 #include "mmath.h"
46 #include "pipeline.h"
47 #include "texstate.h"
48 #include "translate.h"
49 #include "types.h"
50 #include "varray.h"
51 #include "vb.h"
52 #include "vbfill.h"
53 #include "vbrender.h"
54 #include "vbindirect.h"
55 #include "vbxform.h"
56 #include "xform.h"
57 #ifdef XFree86Server
58 #include "GL/xf86glx.h"
59 #endif
60 #endif
61
62 #if defined(GLX_DIRECT_RENDERING) && !defined(XFree86Server) && !defined(GLX_USE_DLOPEN)
63 #define NEED_MESA_FUNCS_WRAPPED
64 #include "mesa_api.h"
65 #endif
66
67
68 void GLAPIENTRY glVertexPointer(CTX_ARG GLint size, GLenum type, GLsizei stride,
69 const GLvoid *ptr )
70 {
71 GLcontext *ctx;
72 GET_CONTEXT;
73 CHECK_CONTEXT;
74 ctx = CC;
75
76 if (size<2 || size>4) {
77 gl_error( ctx, GL_INVALID_VALUE, "glVertexPointer(size)" );
78 return;
79 }
80 if (stride<0) {
81 gl_error( ctx, GL_INVALID_VALUE, "glVertexPointer(stride)" );
82 return;
83 }
84
85 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
86 fprintf(stderr, "glVertexPointer( sz %d type %s stride %d )\n", size,
87 gl_lookup_enum_by_nr( type ),
88 stride);
89
90 ctx->Array.Vertex.StrideB = stride;
91 if (!stride) {
92 switch (type) {
93 case GL_SHORT:
94 ctx->Array.Vertex.StrideB = size*sizeof(GLshort);
95 break;
96 case GL_INT:
97 ctx->Array.Vertex.StrideB = size*sizeof(GLint);
98 break;
99 case GL_FLOAT:
100 ctx->Array.Vertex.StrideB = size*sizeof(GLfloat);
101 break;
102 case GL_DOUBLE:
103 ctx->Array.Vertex.StrideB = size*sizeof(GLdouble);
104 break;
105 default:
106 gl_error( ctx, GL_INVALID_ENUM, "glVertexPointer(type)" );
107 return;
108 }
109 }
110 ctx->Array.Vertex.Size = size;
111 ctx->Array.Vertex.Type = type;
112 ctx->Array.Vertex.Stride = stride;
113 ctx->Array.Vertex.Ptr = (void *) ptr;
114 ctx->Array.VertexFunc = gl_trans_4f_tab[size][TYPE_IDX(type)];
115 ctx->Array.VertexEltFunc = gl_trans_elt_4f_tab[size][TYPE_IDX(type)];
116 ctx->Array.NewArrayState |= VERT_OBJ_ANY;
117 ctx->NewState |= NEW_CLIENT_STATE;
118 }
119
120
121
122
123 void GLAPIENTRY glNormalPointer(CTX_ARG GLenum type, GLsizei stride,
124 const GLvoid *ptr )
125 {
126 GLcontext *ctx;
127 GET_CONTEXT;
128 CHECK_CONTEXT;
129 ctx = CC;
130
131 if (stride<0) {
132 gl_error( ctx, GL_INVALID_VALUE, "glNormalPointer(stride)" );
133 return;
134 }
135
136 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
137 fprintf(stderr, "glNormalPointer( type %s stride %d )\n",
138 gl_lookup_enum_by_nr( type ),
139 stride);
140
141 ctx->Array.Normal.StrideB = stride;
142 if (!stride) {
143 switch (type) {
144 case GL_BYTE:
145 ctx->Array.Normal.StrideB = 3*sizeof(GLbyte);
146 break;
147 case GL_SHORT:
148 ctx->Array.Normal.StrideB = 3*sizeof(GLshort);
149 break;
150 case GL_INT:
151 ctx->Array.Normal.StrideB = 3*sizeof(GLint);
152 break;
153 case GL_FLOAT:
154 ctx->Array.Normal.StrideB = 3*sizeof(GLfloat);
155 break;
156 case GL_DOUBLE:
157 ctx->Array.Normal.StrideB = 3*sizeof(GLdouble);
158 break;
159 default:
160 gl_error( ctx, GL_INVALID_ENUM, "glNormalPointer(type)" );
161 return;
162 }
163 }
164 ctx->Array.Normal.Type = type;
165 ctx->Array.Normal.Stride = stride;
166 ctx->Array.Normal.Ptr = (void *) ptr;
167 ctx->Array.NormalFunc = gl_trans_3f_tab[TYPE_IDX(type)];
168 ctx->Array.NormalEltFunc = gl_trans_elt_3f_tab[TYPE_IDX(type)];
169 ctx->Array.NewArrayState |= VERT_NORM;
170 ctx->NewState |= NEW_CLIENT_STATE;
171 }
172
173
174
175 void GLAPIENTRY glColorPointer(CTX_ARG GLint size, GLenum type, GLsizei stride,
176 const GLvoid *ptr )
177 {
178 GLcontext *ctx;
179 GET_CONTEXT;
180 CHECK_CONTEXT;
181 ctx = CC;
182 if (size<3 || size>4) {
183 gl_error( ctx, GL_INVALID_VALUE, "glColorPointer(size)" );
184 return;
185 }
186 if (stride<0) {
187 gl_error( ctx, GL_INVALID_VALUE, "glColorPointer(stride)" );
188 return;
189 }
190
191 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
192 fprintf(stderr, "glColorPointer( sz %d type %s stride %d )\n", size,
193 gl_lookup_enum_by_nr( type ),
194 stride);
195
196 ctx->Array.Color.StrideB = stride;
197 if (!stride) {
198 switch (type) {
199 case GL_BYTE:
200 ctx->Array.Color.StrideB = size*sizeof(GLbyte);
201 break;
202 case GL_UNSIGNED_BYTE:
203 ctx->Array.Color.StrideB = size*sizeof(GLubyte);
204 break;
205 case GL_SHORT:
206 ctx->Array.Color.StrideB = size*sizeof(GLshort);
207 break;
208 case GL_UNSIGNED_SHORT:
209 ctx->Array.Color.StrideB = size*sizeof(GLushort);
210 break;
211 case GL_INT:
212 ctx->Array.Color.StrideB = size*sizeof(GLint);
213 break;
214 case GL_UNSIGNED_INT:
215 ctx->Array.Color.StrideB = size*sizeof(GLuint);
216 break;
217 case GL_FLOAT:
218 ctx->Array.Color.StrideB = size*sizeof(GLfloat);
219 break;
220 case GL_DOUBLE:
221 ctx->Array.Color.StrideB = size*sizeof(GLdouble);
222 break;
223 default:
224 gl_error( ctx, GL_INVALID_ENUM, "glColorPointer(type)" );
225 return;
226 }
227 }
228 ctx->Array.Color.Size = size;
229 ctx->Array.Color.Type = type;
230 ctx->Array.Color.Stride = stride;
231 ctx->Array.Color.Ptr = (void *) ptr;
232 ctx->Array.ColorFunc = gl_trans_4ub_tab[size][TYPE_IDX(type)];
233 ctx->Array.ColorEltFunc = gl_trans_elt_4ub_tab[size][TYPE_IDX(type)];
234 ctx->Array.NewArrayState |= VERT_RGBA;
235 ctx->NewState |= NEW_CLIENT_STATE;
236 }
237
238
239
240 void GLAPIENTRY glIndexPointer(CTX_ARG GLenum type, GLsizei stride,
241 const GLvoid *ptr )
242 {
243 GLcontext *ctx;
244 GET_CONTEXT;
245 CHECK_CONTEXT;
246 ctx = CC;
247
248 if (stride<0) {
249 gl_error( ctx, GL_INVALID_VALUE, "glIndexPointer(stride)" );
250 return;
251 }
252
253 ctx->Array.Index.StrideB = stride;
254 if (!stride) {
255 switch (type) {
256 case GL_UNSIGNED_BYTE:
257 ctx->Array.Index.StrideB = sizeof(GLubyte);
258 break;
259 case GL_SHORT:
260 ctx->Array.Index.StrideB = sizeof(GLshort);
261 break;
262 case GL_INT:
263 ctx->Array.Index.StrideB = sizeof(GLint);
264 break;
265 case GL_FLOAT:
266 ctx->Array.Index.StrideB = sizeof(GLfloat);
267 break;
268 case GL_DOUBLE:
269 ctx->Array.Index.StrideB = sizeof(GLdouble);
270 break;
271 default:
272 gl_error( ctx, GL_INVALID_ENUM, "glIndexPointer(type)" );
273 return;
274 }
275 }
276 ctx->Array.Index.Type = type;
277 ctx->Array.Index.Stride = stride;
278 ctx->Array.Index.Ptr = (void *) ptr;
279 ctx->Array.IndexFunc = gl_trans_1ui_tab[TYPE_IDX(type)];
280 ctx->Array.IndexEltFunc = gl_trans_elt_1ui_tab[TYPE_IDX(type)];
281 ctx->Array.NewArrayState |= VERT_INDEX;
282 ctx->NewState |= NEW_CLIENT_STATE;
283 }
284
285
286
287 void GLAPIENTRY glTexCoordPointer(CTX_ARG GLint size, GLenum type,
288 GLsizei stride, const GLvoid *ptr )
289 {
290 GLuint texUnit;
291
292 GLcontext *ctx;
293 GET_CONTEXT;
294 CHECK_CONTEXT;
295 ctx = CC;
296
297 texUnit = ctx->Array.ActiveTexture;
298
299 if (size<1 || size>4) {
300 gl_error( ctx, GL_INVALID_VALUE, "glTexCoordPointer(size)" );
301 return;
302 }
303 if (stride<0) {
304 gl_error( ctx, GL_INVALID_VALUE, "glTexCoordPointer(stride)" );
305 return;
306 }
307
308 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
309 fprintf(stderr, "glTexCoordPointer( unit %u sz %d type %s stride %d )\n",
310 texUnit,
311 size,
312 gl_lookup_enum_by_nr( type ),
313 stride);
314
315 ctx->Array.TexCoord[texUnit].StrideB = stride;
316 if (!stride) {
317 switch (type) {
318 case GL_SHORT:
319 ctx->Array.TexCoord[texUnit].StrideB = size*sizeof(GLshort);
320 break;
321 case GL_INT:
322 ctx->Array.TexCoord[texUnit].StrideB = size*sizeof(GLint);
323 break;
324 case GL_FLOAT:
325 ctx->Array.TexCoord[texUnit].StrideB = size*sizeof(GLfloat);
326 break;
327 case GL_DOUBLE:
328 ctx->Array.TexCoord[texUnit].StrideB = size*sizeof(GLdouble);
329 break;
330 default:
331 gl_error( ctx, GL_INVALID_ENUM, "glTexCoordPointer(type)" );
332 return;
333 }
334 }
335 ctx->Array.TexCoord[texUnit].Size = size;
336 ctx->Array.TexCoord[texUnit].Type = type;
337 ctx->Array.TexCoord[texUnit].Stride = stride;
338 ctx->Array.TexCoord[texUnit].Ptr = (void *) ptr;
339
340 ctx->Array.TexCoordFunc[texUnit] = gl_trans_4f_tab[size][TYPE_IDX(type)];
341 ctx->Array.TexCoordEltFunc[texUnit] = gl_trans_elt_4f_tab[size][TYPE_IDX(type)];
342 ctx->Array.NewArrayState |= PIPE_TEX(texUnit);
343 ctx->NewState |= NEW_CLIENT_STATE;
344 }
345
346
347
348
349 void GLAPIENTRY glEdgeFlagPointer(CTX_ARG GLsizei stride, const void *vptr )
350 {
351 const GLboolean *ptr = (GLboolean *)vptr;
352
353 GLcontext *ctx;
354 GET_CONTEXT;
355 CHECK_CONTEXT;
356 ctx = CC;
357
358 if (stride<0) {
359 gl_error( ctx, GL_INVALID_VALUE, "glEdgeFlagPointer(stride)" );
360 return;
361 }
362 ctx->Array.EdgeFlag.Stride = stride;
363 ctx->Array.EdgeFlag.StrideB = stride ? stride : sizeof(GLboolean);
364 ctx->Array.EdgeFlag.Ptr = (GLboolean *) ptr;
365 if (stride != sizeof(GLboolean)) {
366 ctx->Array.EdgeFlagFunc = gl_trans_1ub_tab[TYPE_IDX(GL_UNSIGNED_BYTE)];
367 } else {
368 ctx->Array.EdgeFlagFunc = 0;
369 }
370 ctx->Array.EdgeFlagEltFunc = gl_trans_elt_1ub_tab[TYPE_IDX(GL_UNSIGNED_BYTE)];
371 ctx->Array.NewArrayState |= VERT_EDGE;
372 ctx->NewState |= NEW_CLIENT_STATE;
373 }
374
375
376 /* Called only from gl_DrawElements
377 */
378 void gl_CVAEltPointer( GLcontext *ctx, GLenum type, const GLvoid *ptr )
379 {
380 switch (type) {
381 case GL_UNSIGNED_BYTE:
382 ctx->CVA.Elt.StrideB = sizeof(GLubyte);
383 break;
384 case GL_UNSIGNED_SHORT:
385 ctx->CVA.Elt.StrideB = sizeof(GLushort);
386 break;
387 case GL_UNSIGNED_INT:
388 ctx->CVA.Elt.StrideB = sizeof(GLuint);
389 break;
390 default:
391 gl_error( ctx, GL_INVALID_ENUM, "glEltPointer(type)" );
392 return;
393 }
394 ctx->CVA.Elt.Type = type;
395 ctx->CVA.Elt.Stride = 0;
396 ctx->CVA.Elt.Ptr = (void *) ptr;
397 ctx->CVA.EltFunc = gl_trans_1ui_tab[TYPE_IDX(type)];
398 ctx->Array.NewArrayState |= VERT_ELT; /* ??? */
399 }
400
401
402
403 /* KW: Batch function to exec all the array elements in the input
404 * buffer prior to transform. Done only the first time a vertex
405 * buffer is executed or compiled.
406 *
407 * KW: Have to do this after each glEnd if cva isn't active. (also
408 * have to do it after each full buffer)
409 */
410 void gl_exec_array_elements( GLcontext *ctx, struct immediate *IM,
411 GLuint start,
412 GLuint count)
413 {
414 GLuint *flags = IM->Flag;
415 GLuint *elts = IM->Elt;
416 GLuint translate = ctx->Array.Flags;
417 GLuint i;
418
419 if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
420 fprintf(stderr, "exec_array_elements %d .. %d\n", start, count);
421
422 if (translate & VERT_OBJ_ANY)
423 (ctx->Array.VertexEltFunc)( IM->Obj,
424 &ctx->Array.Vertex,
425 flags, elts, (VERT_ELT|VERT_OBJ_ANY),
426 start, count);
427
428 if (translate & VERT_NORM)
429 (ctx->Array.NormalEltFunc)( IM->Normal,
430 &ctx->Array.Normal,
431 flags, elts, (VERT_ELT|VERT_NORM),
432 start, count);
433
434 if (translate & VERT_EDGE)
435 (ctx->Array.EdgeFlagEltFunc)( IM->EdgeFlag,
436 &ctx->Array.EdgeFlag,
437 flags, elts, (VERT_ELT|VERT_EDGE),
438 start, count);
439
440 if (translate & VERT_RGBA)
441 (ctx->Array.ColorEltFunc)( IM->Color,
442 &ctx->Array.Color,
443 flags, elts, (VERT_ELT|VERT_RGBA),
444 start, count);
445
446 if (translate & VERT_INDEX)
447 (ctx->Array.IndexEltFunc)( IM->Index,
448 &ctx->Array.Index,
449 flags, elts, (VERT_ELT|VERT_INDEX),
450 start, count);
451
452 if (translate & VERT_TEX0_ANY)
453 (ctx->Array.TexCoordEltFunc[0])( IM->TexCoord[0],
454 &ctx->Array.TexCoord[0],
455 flags, elts, (VERT_ELT|VERT_TEX0_ANY),
456 start, count);
457
458 if (translate & VERT_TEX1_ANY)
459 (ctx->Array.TexCoordEltFunc[1])( IM->TexCoord[1],
460 &ctx->Array.TexCoord[1],
461 flags, elts, (VERT_ELT|VERT_TEX1_ANY),
462 start, count);
463
464 /* Lighting ignores the and-flag, so still need to do this.
465 */
466 /* fprintf(stderr, "start %d count %d\n", start, count); */
467 /* gl_print_vert_flags("translate", translate); */
468
469 for (i = start ; i < count ; i++)
470 if (flags[i] & VERT_ELT) {
471 /* flags[i] &= ~VERT_ELT; */
472 flags[i] |= translate;
473 }
474 }
475
476
477
478 /* KW: I think this is moving in the right direction, but it still feels
479 * like we are doing way too much work.
480 */
481 void gl_DrawArrays( GLcontext *ctx, GLenum mode, GLint start, GLsizei count )
482 {
483 struct vertex_buffer *VB = ctx->VB;
484 GLint i;
485
486 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDrawArrays");
487
488 if (count<0) {
489 gl_error( ctx, GL_INVALID_VALUE, "glDrawArrays(count)" );
490 return;
491 }
492
493 if (!ctx->CompileFlag && ctx->Array.Vertex.Enabled)
494 {
495 GLint remaining = count;
496 GLint i;
497 GLvector4f obj;
498 GLvector3f norm;
499 GLvector4f tc[MAX_TEXTURE_UNITS];
500 GLvector4ub col;
501 GLvector1ub edge;
502 GLvector1ui index;
503 GLuint update = 0, translate = 0;
504 struct vertex_array_pointers VSrc;
505 struct immediate *IM = VB->IM;
506 struct gl_client_array *client_data;
507 struct gl_pipeline *elt = &ctx->CVA.elt;
508 GLboolean relock;
509 GLuint fallback, required;
510
511 if (ctx->NewState)
512 gl_update_state( ctx );
513
514 /* This will die miserably with CVA... Need more work to support this.
515 */
516 relock = ctx->CompileCVAFlag;
517 ctx->CompileCVAFlag = 0;
518
519 if (!elt->pipeline_valid || relock)
520 gl_build_immediate_pipeline( ctx );
521
522 required = elt->inputs;
523 fallback = (elt->inputs & ~ctx->Array.Summary);
524
525 VSrc.Color = &IM->v.Color;
526 VSrc.Index = &IM->v.Index;
527 VSrc.EdgeFlag = &IM->v.EdgeFlag;
528 VSrc.TexCoord[0] = &IM->v.TexCoord[0];
529 VSrc.TexCoord[1] = &IM->v.TexCoord[1];
530 VSrc.Obj = &IM->v.Obj;
531 VSrc.Normal = &IM->v.Normal;
532
533 if (required & VERT_RGBA)
534 {
535 client_data = &ctx->Array.Color;
536 if (fallback & VERT_RGBA)
537 client_data = &ctx->Fallback.Color;
538
539 translate |= VERT_RGBA;
540 }
541
542 if (required & VERT_INDEX)
543 {
544 client_data = &ctx->Array.Index;
545 if (fallback & VERT_INDEX)
546 client_data = &ctx->Fallback.Index;
547
548 translate |= VERT_INDEX;
549 }
550
551 for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++)
552 {
553 GLuint flag = VERT_TEX_ANY(i);
554
555 if (required & flag) {
556
557 client_data = &ctx->Array.TexCoord[i];
558
559 if (fallback & flag)
560 {
561 client_data = &ctx->Fallback.TexCoord[i];
562 client_data->Size = gl_texcoord_size( ctx->Current.Flag, i );
563 }
564
565 translate |= flag;
566 }
567 }
568
569 if (ctx->Array.Flags != ctx->Array.Flag[0])
570 for (i = 0 ; i < VB_MAX ; i++)
571 ctx->Array.Flag[i] = ctx->Array.Flags;
572
573
574 translate |= VERT_OBJ_ANY;
575
576 if (required & VERT_NORM)
577 {
578 client_data = &ctx->Array.Normal;
579 if (fallback & VERT_NORM)
580 client_data = &ctx->Fallback.Normal;
581
582 translate |= VERT_NORM;
583 }
584
585 if ( (required & VERT_EDGE) &&
586 (mode == GL_TRIANGLES ||
587 mode == GL_QUADS ||
588 mode == GL_POLYGON))
589 {
590 client_data = &ctx->Array.EdgeFlag;
591
592 if (fallback & VERT_EDGE)
593 client_data = &ctx->Fallback.EdgeFlag;
594
595 translate |= VERT_EDGE;
596 }
597
598 VB->Primitive = IM->Primitive;
599 VB->NextPrimitive = IM->NextPrimitive;
600 VB->MaterialMask = IM->MaterialMask;
601 VB->Material = IM->Material;
602 VB->BoundsPtr = 0;
603
604 while (remaining > 0) {
605 GLint vbspace = VB_MAX - VB_START;
606 GLuint count, n;
607
608
609 if (vbspace >= remaining) {
610 n = remaining;
611 VB->LastPrimitive = VB_START + n;
612 } else {
613 n = vbspace;
614 VB->LastPrimitive = VB_START;
615 }
616
617 VB->CullMode = 0;
618
619
620 /* Update pointers.
621 */
622 /* Disabled - always do the copy. No real loss
623 * until we improve vertex copying anyway.
624 */
625 if (0) {
626 if (update & VERT_OBJ_ANY)
627 obj.start = VEC_ELT(&obj, GLfloat, start);
628
629 if (update & VERT_NORM)
630 norm.start = VEC_ELT(&norm, GLfloat, start);
631
632 if (update & VERT_EDGE)
633 edge.start = VEC_ELT(&edge, GLubyte, start);
634
635 if (update & VERT_RGBA)
636 col.start = VEC_ELT(&col, GLubyte, start);
637
638 if (update & VERT_INDEX)
639 index.start = VEC_ELT(&index, GLuint, start);
640
641 if (update & VERT_TEX0_ANY)
642 tc[0].start = VEC_ELT(&tc[0], GLfloat, start);
643
644 if (update & VERT_TEX1_ANY)
645 tc[1].start = VEC_ELT(&tc[1], GLfloat, start);
646 }
647
648
649 /* Translate data to fix up type and stride.
650 */
651 if (translate) {
652 if (translate & VERT_OBJ_ANY) {
653 ctx->Array.VertexFunc( IM->Obj + VB_START,
654 &ctx->Array.Vertex, start, n );
655 }
656
657 if (translate & VERT_NORM) {
658 ctx->Array.NormalFunc( IM->Normal + VB_START,
659 &ctx->Array.Normal, start, n );
660 }
661
662 if (translate & VERT_EDGE) {
663 ctx->Array.EdgeFlagFunc( IM->EdgeFlag + VB_START,
664 &ctx->Array.EdgeFlag, start, n );
665 }
666
667 if (translate & VERT_RGBA) {
668 ctx->Array.ColorFunc( IM->Color + VB_START,
669 &ctx->Array.Color, start, n );
670 }
671
672 if (translate & VERT_INDEX) {
673 ctx->Array.IndexFunc( IM->Index + VB_START,
674 &ctx->Array.Index, start, n );
675 }
676
677 if (translate & VERT_TEX0_ANY) {
678 IM->v.TexCoord[0].size = tc[0].size;
679 ctx->Array.TexCoordFunc[0]( IM->TexCoord[0] + VB_START,
680 &ctx->Array.TexCoord[0], start, n );
681 }
682
683 if (translate & VERT_TEX1_ANY) {
684 IM->v.TexCoord[1].size = tc[1].size;
685 ctx->Array.TexCoordFunc[1]( IM->TexCoord[1] + VB_START,
686 &ctx->Array.TexCoord[1], start, n );
687 }
688 }
689
690
691 VB->ObjPtr = VSrc.Obj;
692 VB->NormalPtr = VSrc.Normal;
693 VB->Color[0] = VB->Color[1] = VB->ColorPtr = VSrc.Color;
694 VB->IndexPtr = VSrc.Index;
695 VB->EdgeFlagPtr = VSrc.EdgeFlag;
696 VB->TexCoordPtr[0] = VSrc.TexCoord[0];
697 VB->TexCoordPtr[1] = VSrc.TexCoord[1];
698
699 VB->Flag = ctx->Array.Flag;
700 VB->OrFlag = ctx->Array.Flags;
701
702 count = VB->Count = VB_START + n;
703
704 VB->ObjPtr->count = count;
705 VB->NormalPtr->count = count;
706 VB->ColorPtr->count = count;
707 VB->IndexPtr->count = count;
708 VB->EdgeFlagPtr->count = count;
709 VB->TexCoordPtr[0]->count = count;
710 VB->TexCoordPtr[1]->count = count;
711
712 VB->Flag[count] |= VERT_END_VB;
713 VB->Flag[VB_START] |= VERT_NORM;
714
715 VB->NextPrimitive[VB->CopyStart] = VB->Count;
716 VB->Primitive[VB->CopyStart] = mode;
717
718 /* Transform and render.
719 */
720 gl_run_pipeline( VB );
721 gl_reset_vb( VB );
722
723 ctx->Array.Flag[count] = ctx->Array.Flags;
724 ctx->Array.Flag[VB_START] = ctx->Array.Flags;
725 IM->Flag[VB_START] = 0;
726
727 start += n;
728 remaining -= n;
729 }
730
731 ctx->CompileCVAFlag = relock;
732 }
733 else if (ctx->Array.Vertex.Enabled)
734 {
735 /* The GL_COMPILE and GL_COMPILE_AND_EXECUTE cases. These
736 * could be handled by the above code, but it gets a little
737 * complex.
738 */
739 /* No need to reset - never called from inside a display list */
740 gl_Begin( ctx, mode );
741 for (i=0;i<count;i++) {
742 gl_ArrayElement( ctx, start+i );
743 }
744 gl_End( ctx );
745 }
746 else
747 {
748 /* The degenerate case where vertices are not enabled - only
749 * need to process the very final array element, as all of the
750 * preceding ones would be overwritten anyway.
751 */
752 gl_Begin( ctx, mode );
753 gl_ArrayElement( ctx, start+count );
754 gl_End( ctx );
755 }
756 }
757
758
759
760 /* KW: Exactly fakes the effects of calling glArrayElement multiple times.
761 * Compilation is handled via. the IM->maybe_transform_vb() callback.
762 */
763 #if 1
764 #define DRAW_ELT(FUNC, TYPE) \
765 static void FUNC( GLcontext *ctx, GLenum mode, \
766 TYPE *indices, GLuint count ) \
767 { \
768 GLuint i,j; \
769 \
770 gl_Begin( ctx, mode ); \
771 \
772 for (j = 0 ; j < count ; ) { \
773 struct immediate *IM = ctx->input; \
774 GLuint start = IM->Start; \
775 GLuint nr = MIN2( VB_MAX, count - j + start ); \
776 GLuint sf = IM->Flag[start]; \
777 IM->FlushElt |= IM->ArrayEltFlush; \
778 \
779 for (i = start ; i < nr ; i++) { \
780 IM->Elt[i] = (GLuint) *indices++; \
781 IM->Flag[i] = VERT_ELT; \
782 } \
783 \
784 if (j == 0) IM->Flag[start] |= sf; \
785 \
786 IM->Count = nr; \
787 j += nr - start; \
788 \
789 if (j == count) gl_End( ctx ); \
790 IM->maybe_transform_vb( IM ); \
791 } \
792 }
793 #else
794 #define DRAW_ELT(FUNC, TYPE) \
795 static void FUNC( GLcontext *ctx, GLenum mode, \
796 TYPE *indices, GLuint count ) \
797 { \
798 int i; \
799 glBegin(mode); \
800 for (i = 0 ; i < count ; i++) \
801 glArrayElement( indices[i] ); \
802 glEnd(); \
803 }
804 #endif
805
806
807 DRAW_ELT( draw_elt_ubyte, GLubyte )
808 DRAW_ELT( draw_elt_ushort, GLushort )
809 DRAW_ELT( draw_elt_uint, GLuint )
810
811
812 static GLuint natural_stride[0x10] =
813 {
814 sizeof(GLbyte), /* 0 */
815 sizeof(GLubyte), /* 1 */
816 sizeof(GLshort), /* 2 */
817 sizeof(GLushort), /* 3 */
818 sizeof(GLint), /* 4 */
819 sizeof(GLuint), /* 5 */
820 sizeof(GLfloat), /* 6 */
821 2 * sizeof(GLbyte), /* 7 */
822 3 * sizeof(GLbyte), /* 8 */
823 4 * sizeof(GLbyte), /* 9 */
824 sizeof(GLdouble), /* a */
825 0, /* b */
826 0, /* c */
827 0, /* d */
828 0, /* e */
829 0 /* f */
830 };
831
832 void GLAPIENTRY glDrawElements(CTX_ARG GLenum mode, GLsizei count,
833 GLenum type, const GLvoid *indices )
834 {
835 GLcontext *ctx;
836 struct gl_cva *cva;
837
838 GET_CONTEXT;
839 CHECK_CONTEXT;
840 ctx = CC;
841
842 cva = &ctx->CVA;
843 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDrawElements");
844
845 if (count <= 0) {
846 if (count < 0)
847 gl_error( ctx, GL_INVALID_VALUE, "glDrawElements(count)" );
848 return;
849 }
850
851 if (mode < 0 || mode > GL_POLYGON) {
852 gl_error( ctx, GL_INVALID_ENUM, "glDrawArrays(mode)" );
853 return;
854 }
855
856 if (type != GL_UNSIGNED_INT && type != GL_UNSIGNED_BYTE && type != GL_UNSIGNED_SHORT)
857 {
858 gl_error( ctx, GL_INVALID_ENUM, "glDrawElements(type)" );
859 return;
860 }
861
862 if (ctx->NewState)
863 gl_update_state(ctx);
864
865 if (ctx->CompileCVAFlag)
866 {
867 #if defined(MESA_CVA_PROF)
868 force_init_prof();
869 #endif
870
871 /* Treat VERT_ELT like a special client array.
872 */
873 ctx->Array.NewArrayState |= VERT_ELT;
874 ctx->Array.Summary |= VERT_ELT;
875 ctx->Array.Flags |= VERT_ELT;
876
877 cva->elt_mode = mode;
878 cva->elt_count = count;
879 cva->Elt.Type = type;
880 cva->Elt.Ptr = (void *) indices;
881 cva->Elt.StrideB = natural_stride[TYPE_IDX(type)];
882 cva->EltFunc = gl_trans_1ui_tab[TYPE_IDX(type)];
883
884 if (!cva->pre.pipeline_valid)
885 gl_build_precalc_pipeline( ctx );
886 else if (MESA_VERBOSE & VERBOSE_PIPELINE)
887 fprintf(stderr, ": dont rebuild\n");
888
889 gl_cva_force_precalc( ctx );
890
891 /* Did we 'precalculate' the render op?
892 */
893 if (ctx->CVA.pre.ops & PIPE_OP_RENDER) {
894 ctx->Array.NewArrayState |= VERT_ELT;
895 ctx->Array.Summary &= ~VERT_ELT;
896 ctx->Array.Flags &= ~VERT_ELT;
897 return;
898 }
899
900 if ( (MESA_VERBOSE&VERBOSE_VARRAY) )
901 printf("using immediate\n");
902 }
903
904
905 /* Otherwise, have to use the immediate path to render.
906 */
907 switch (type) {
908 case GL_UNSIGNED_BYTE:
909 {
910 GLubyte *ub_indices = (GLubyte *) indices;
911 if (ctx->Array.Summary & VERT_OBJ_ANY) {
912 draw_elt_ubyte( ctx, mode, ub_indices, count );
913 } else {
914 gl_ArrayElement( ctx, (GLuint) ub_indices[count-1] );
915 }
916 }
917 break;
918 case GL_UNSIGNED_SHORT:
919 {
920 GLushort *us_indices = (GLushort *) indices;
921 if (ctx->Array.Summary & VERT_OBJ_ANY) {
922 draw_elt_ushort( ctx, mode, us_indices, count );
923 } else {
924 gl_ArrayElement( ctx, (GLuint) us_indices[count-1] );
925 }
926 }
927 break;
928 case GL_UNSIGNED_INT:
929 {
930 GLuint *ui_indices = (GLuint *) indices;
931 if (ctx->Array.Summary & VERT_OBJ_ANY) {
932 draw_elt_uint( ctx, mode, ui_indices, count );
933 } else {
934 gl_ArrayElement( ctx, ui_indices[count-1] );
935 }
936 }
937 break;
938 default:
939 gl_error( ctx, GL_INVALID_ENUM, "glDrawElements(type)" );
940 break;
941 }
942
943 if (ctx->CompileCVAFlag) {
944 ctx->Array.NewArrayState |= VERT_ELT;
945 ctx->Array.Summary &= ~VERT_ELT;
946 }
947 }
948
949
950
951 void GLAPIENTRY glInterleavedArrays(CTX_ARG GLenum format, GLsizei stride,
952 const GLvoid *pointer )
953 {
954 GLcontext *ctx;
955 GLboolean tflag, cflag, nflag; /* enable/disable flags */
956 GLint tcomps, ccomps, vcomps; /* components per texcoord, color, vertex */
957
958 GLenum ctype; /* color type */
959 GLint coffset, noffset, voffset;/* color, normal, vertex offsets */
960 GLint defstride; /* default stride */
961 GLint c, f;
962 GLint coordUnitSave;
963
964 GET_CONTEXT;
965 CHECK_CONTEXT;
966 ctx = CC;
967
968
969 f = sizeof(GLfloat);
970 c = f * ((4*sizeof(GLubyte) + (f-1)) / f);
971
972 if (stride<0) {
973 gl_error( ctx, GL_INVALID_VALUE, "glInterleavedArrays(stride)" );
974 return;
975 }
976
977 switch (format) {
978 case GL_V2F:
979 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_FALSE;
980 tcomps = 0; ccomps = 0; vcomps = 2;
981 voffset = 0;
982 defstride = 2*f;
983 break;
984 case GL_V3F:
985 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_FALSE;
986 tcomps = 0; ccomps = 0; vcomps = 3;
987 voffset = 0;
988 defstride = 3*f;
989 break;
990 case GL_C4UB_V2F:
991 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
992 tcomps = 0; ccomps = 4; vcomps = 2;
993 ctype = GL_UNSIGNED_BYTE;
994 coffset = 0;
995 voffset = c;
996 defstride = c + 2*f;
997 break;
998 case GL_C4UB_V3F:
999 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
1000 tcomps = 0; ccomps = 4; vcomps = 3;
1001 ctype = GL_UNSIGNED_BYTE;
1002 coffset = 0;
1003 voffset = c;
1004 defstride = c + 3*f;
1005 break;
1006 case GL_C3F_V3F:
1007 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
1008 tcomps = 0; ccomps = 3; vcomps = 3;
1009 ctype = GL_FLOAT;
1010 coffset = 0;
1011 voffset = 3*f;
1012 defstride = 6*f;
1013 break;
1014 case GL_N3F_V3F:
1015 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_TRUE;
1016 tcomps = 0; ccomps = 0; vcomps = 3;
1017 noffset = 0;
1018 voffset = 3*f;
1019 defstride = 6*f;
1020 break;
1021 case GL_C4F_N3F_V3F:
1022 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_TRUE;
1023 tcomps = 0; ccomps = 4; vcomps = 3;
1024 ctype = GL_FLOAT;
1025 coffset = 0;
1026 noffset = 4*f;
1027 voffset = 7*f;
1028 defstride = 10*f;
1029 break;
1030 case GL_T2F_V3F:
1031 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_FALSE;
1032 tcomps = 2; ccomps = 0; vcomps = 3;
1033 voffset = 2*f;
1034 defstride = 5*f;
1035 break;
1036 case GL_T4F_V4F:
1037 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_FALSE;
1038 tcomps = 4; ccomps = 0; vcomps = 4;
1039 voffset = 4*f;
1040 defstride = 8*f;
1041 break;
1042 case GL_T2F_C4UB_V3F:
1043 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_FALSE;
1044 tcomps = 2; ccomps = 4; vcomps = 3;
1045 ctype = GL_UNSIGNED_BYTE;
1046 coffset = 2*f;
1047 voffset = c+2*f;
1048 defstride = c+5*f;
1049 break;
1050 case GL_T2F_C3F_V3F:
1051 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_FALSE;
1052 tcomps = 2; ccomps = 3; vcomps = 3;
1053 ctype = GL_FLOAT;
1054 coffset = 2*f;
1055 voffset = 5*f;
1056 defstride = 8*f;
1057 break;
1058 case GL_T2F_N3F_V3F:
1059 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_TRUE;
1060 tcomps = 2; ccomps = 0; vcomps = 3;
1061 noffset = 2*f;
1062 voffset = 5*f;
1063 defstride = 8*f;
1064 break;
1065 case GL_T2F_C4F_N3F_V3F:
1066 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_TRUE;
1067 tcomps = 2; ccomps = 4; vcomps = 3;
1068 ctype = GL_FLOAT;
1069 coffset = 2*f;
1070 noffset = 6*f;
1071 voffset = 9*f;
1072 defstride = 12*f;
1073 break;
1074 case GL_T4F_C4F_N3F_V4F:
1075 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_TRUE;
1076 tcomps = 4; ccomps = 4; vcomps = 4;
1077 ctype = GL_FLOAT;
1078 coffset = 4*f;
1079 noffset = 8*f;
1080 voffset = 11*f;
1081 defstride = 15*f;
1082 break;
1083 default:
1084 gl_error( ctx, GL_INVALID_ENUM, "glInterleavedArrays(format)" );
1085 return;
1086 }
1087
1088 if (stride==0) {
1089 stride = defstride;
1090 }
1091
1092 gl_DisableClientState( ctx, GL_EDGE_FLAG_ARRAY );
1093 gl_DisableClientState( ctx, GL_INDEX_ARRAY );
1094
1095 /* Texcoords */
1096 coordUnitSave = ctx->Array.ActiveTexture;
1097 if (tflag) {
1098 GLint i;
1099 GLint factor = ctx->Array.TexCoordInterleaveFactor;
1100 for (i = 0; i < factor; i++) {
1101 gl_ActiveTexture( ctx, (GLenum) (GL_TEXTURE0_ARB + i) );
1102 gl_EnableClientState( ctx, GL_TEXTURE_COORD_ARRAY );
1103 glTexCoordPointer(CTX_PRM tcomps, GL_FLOAT, stride,
1104 (GLubyte *) pointer + i * coffset );
1105 }
1106 for (i = factor; i < ctx->Const.MaxTextureUnits; i++) {
1107 gl_ActiveTexture( ctx, (GLenum) (GL_TEXTURE0_ARB + i) );
1108 gl_DisableClientState( ctx, GL_TEXTURE_COORD_ARRAY );
1109 }
1110 }
1111 else {
1112 GLint i;
1113 for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
1114 gl_ActiveTexture( ctx, (GLenum) (GL_TEXTURE0_ARB + i) );
1115 gl_DisableClientState( ctx, GL_TEXTURE_COORD_ARRAY );
1116 }
1117 }
1118 /* Restore texture coordinate unit index */
1119 gl_ActiveTexture( ctx, (GLenum) (GL_TEXTURE0_ARB + coordUnitSave) );
1120
1121
1122 /* Color */
1123 if (cflag) {
1124 gl_EnableClientState( ctx, GL_COLOR_ARRAY );
1125 glColorPointer(CTX_PRM ccomps, ctype, stride,
1126 (GLubyte*) pointer + coffset );
1127 }
1128 else {
1129 gl_DisableClientState( ctx, GL_COLOR_ARRAY );
1130 }
1131
1132
1133 /* Normals */
1134 if (nflag) {
1135 gl_EnableClientState( ctx, GL_NORMAL_ARRAY );
1136 glNormalPointer(CTX_PRM GL_FLOAT, stride,
1137 (GLubyte*) pointer + noffset );
1138 }
1139 else {
1140 gl_DisableClientState( ctx, GL_NORMAL_ARRAY );
1141 }
1142
1143 gl_EnableClientState( ctx, GL_VERTEX_ARRAY );
1144 glVertexPointer(CTX_PRM vcomps, GL_FLOAT, stride,
1145 (GLubyte *) pointer + voffset );
1146 }
1147
1148
1149
1150 void GLAPIENTRY glDrawRangeElements(CTX_ARG GLenum mode, GLuint start,
1151 GLuint end, GLsizei count,
1152 GLenum type, const GLvoid *indices )
1153 {
1154 GLcontext *ctx;
1155 GET_CONTEXT;
1156 CHECK_CONTEXT;
1157 ctx = CC;
1158
1159 if (end < start) {
1160 gl_error(ctx, GL_INVALID_VALUE, "glDrawRangeElements( end < start )");
1161 return;
1162 }
1163
1164 if (!ctx->Array.LockCount && 2*count > (GLint) 3*(end-start)) {
1165 glLockArraysEXT(CTX_PRM start, end );
1166 glDrawElements(CTX_PRM mode, count, type, indices );
1167 glUnlockArraysEXT(CTX_VPRM );
1168 } else {
1169 glDrawElements(CTX_PRM mode, count, type, indices );
1170 }
1171 }
1172
1173
1174
1175 void gl_update_client_state( GLcontext *ctx )
1176 {
1177 static GLuint sz_flags[5] = { 0,
1178 0,
1179 VERT_OBJ_2,
1180 VERT_OBJ_23,
1181 VERT_OBJ_234 };
1182
1183 static GLuint tc_flags[5] = { 0,
1184 VERT_TEX0_1,
1185 VERT_TEX0_12,
1186 VERT_TEX0_123,
1187 VERT_TEX0_1234 };
1188
1189 ctx->Array.Flags = 0;
1190 ctx->Array.Summary = 0;
1191 ctx->input->ArrayIncr = 0;
1192
1193 if (ctx->Array.Normal.Enabled) ctx->Array.Flags |= VERT_NORM;
1194 if (ctx->Array.Color.Enabled) ctx->Array.Flags |= VERT_RGBA;
1195 if (ctx->Array.Index.Enabled) ctx->Array.Flags |= VERT_INDEX;
1196 if (ctx->Array.EdgeFlag.Enabled) ctx->Array.Flags |= VERT_EDGE;
1197 if (ctx->Array.Vertex.Enabled) {
1198 ctx->Array.Flags |= sz_flags[ctx->Array.Vertex.Size];
1199 ctx->input->ArrayIncr = 1;
1200 }
1201 if (ctx->Array.TexCoord[0].Enabled) {
1202 ctx->Array.Flags |= tc_flags[ctx->Array.TexCoord[0].Size];
1203 }
1204 if (ctx->Array.TexCoord[1].Enabled) {
1205 ctx->Array.Flags |= (tc_flags[ctx->Array.TexCoord[1].Size] << NR_TEXSIZE_BITS);
1206 }
1207
1208 /* Not really important any more:
1209 */
1210 ctx->Array.Summary = ctx->Array.Flags & VERT_DATA;
1211 ctx->input->ArrayAndFlags = ~ctx->Array.Flags;
1212 ctx->input->ArrayEltFlush = !(ctx->CompileCVAFlag);
1213 }
1214