96b15c27f071a6b1708799dab0070c08ba158347
[mesa.git] / src / mesa / main / varray.c
1 /* $Id: varray.c,v 1.29 2000/10/30 18:50:42 keithw Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.5
6 *
7 * Copyright (C) 1999-2000 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 #include "glheader.h"
31 #include "context.h"
32 #include "cva.h"
33 #include "enable.h"
34 #include "enums.h"
35 #include "dlist.h"
36 #include "light.h"
37 #include "macros.h"
38 #include "mmath.h"
39 #include "pipeline.h"
40 #include "state.h"
41 #include "texstate.h"
42 #include "translate.h"
43 #include "types.h"
44 #include "varray.h"
45 #include "vb.h"
46 #include "vbfill.h"
47 #include "vbrender.h"
48 #include "vbindirect.h"
49 #include "vbxform.h"
50 #include "xform.h"
51 #endif
52
53
54
55 void
56 _mesa_VertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
57 {
58 GET_CURRENT_CONTEXT(ctx);
59
60 if (size<2 || size>4) {
61 gl_error( ctx, GL_INVALID_VALUE, "glVertexPointer(size)" );
62 return;
63 }
64 if (stride<0) {
65 gl_error( ctx, GL_INVALID_VALUE, "glVertexPointer(stride)" );
66 return;
67 }
68
69 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
70 fprintf(stderr, "glVertexPointer( sz %d type %s stride %d )\n", size,
71 gl_lookup_enum_by_nr( type ),
72 stride);
73
74 ctx->Array.Vertex.StrideB = stride;
75 if (!stride) {
76 switch (type) {
77 case GL_SHORT:
78 ctx->Array.Vertex.StrideB = size*sizeof(GLshort);
79 break;
80 case GL_INT:
81 ctx->Array.Vertex.StrideB = size*sizeof(GLint);
82 break;
83 case GL_FLOAT:
84 ctx->Array.Vertex.StrideB = size*sizeof(GLfloat);
85 break;
86 case GL_DOUBLE:
87 ctx->Array.Vertex.StrideB = size*sizeof(GLdouble);
88 break;
89 default:
90 gl_error( ctx, GL_INVALID_ENUM, "glVertexPointer(type)" );
91 return;
92 }
93 }
94 ctx->Array.Vertex.Size = size;
95 ctx->Array.Vertex.Type = type;
96 ctx->Array.Vertex.Stride = stride;
97 ctx->Array.Vertex.Ptr = (void *) ptr;
98 ctx->Array.VertexFunc = gl_trans_4f_tab[size][TYPE_IDX(type)];
99 ctx->Array.VertexEltFunc = gl_trans_elt_4f_tab[size][TYPE_IDX(type)];
100 ctx->Array.NewArrayState |= VERT_OBJ_ANY;
101 ctx->NewState |= _NEW_ARRAY;
102 }
103
104
105
106
107 void
108 _mesa_NormalPointer(GLenum type, GLsizei stride, const GLvoid *ptr )
109 {
110 GET_CURRENT_CONTEXT(ctx);
111
112 if (stride<0) {
113 gl_error( ctx, GL_INVALID_VALUE, "glNormalPointer(stride)" );
114 return;
115 }
116
117 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
118 fprintf(stderr, "glNormalPointer( type %s stride %d )\n",
119 gl_lookup_enum_by_nr( type ),
120 stride);
121
122 ctx->Array.Normal.StrideB = stride;
123 if (!stride) {
124 switch (type) {
125 case GL_BYTE:
126 ctx->Array.Normal.StrideB = 3*sizeof(GLbyte);
127 break;
128 case GL_SHORT:
129 ctx->Array.Normal.StrideB = 3*sizeof(GLshort);
130 break;
131 case GL_INT:
132 ctx->Array.Normal.StrideB = 3*sizeof(GLint);
133 break;
134 case GL_FLOAT:
135 ctx->Array.Normal.StrideB = 3*sizeof(GLfloat);
136 break;
137 case GL_DOUBLE:
138 ctx->Array.Normal.StrideB = 3*sizeof(GLdouble);
139 break;
140 default:
141 gl_error( ctx, GL_INVALID_ENUM, "glNormalPointer(type)" );
142 return;
143 }
144 }
145 ctx->Array.Normal.Type = type;
146 ctx->Array.Normal.Stride = stride;
147 ctx->Array.Normal.Ptr = (void *) ptr;
148 ctx->Array.NormalFunc = gl_trans_3f_tab[TYPE_IDX(type)];
149 ctx->Array.NormalEltFunc = gl_trans_elt_3f_tab[TYPE_IDX(type)];
150 ctx->Array.NewArrayState |= VERT_NORM;
151 ctx->NewState |= _NEW_ARRAY;
152 }
153
154
155
156 void
157 _mesa_ColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
158 {
159 GET_CURRENT_CONTEXT(ctx);
160
161 if (size<3 || size>4) {
162 gl_error( ctx, GL_INVALID_VALUE, "glColorPointer(size)" );
163 return;
164 }
165 if (stride<0) {
166 gl_error( ctx, GL_INVALID_VALUE, "glColorPointer(stride)" );
167 return;
168 }
169
170 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
171 fprintf(stderr, "glColorPointer( sz %d type %s stride %d )\n", size,
172 gl_lookup_enum_by_nr( type ),
173 stride);
174
175 ctx->Array.Color.StrideB = stride;
176 if (!stride) {
177 switch (type) {
178 case GL_BYTE:
179 ctx->Array.Color.StrideB = size*sizeof(GLbyte);
180 break;
181 case GL_UNSIGNED_BYTE:
182 ctx->Array.Color.StrideB = size*sizeof(GLubyte);
183 break;
184 case GL_SHORT:
185 ctx->Array.Color.StrideB = size*sizeof(GLshort);
186 break;
187 case GL_UNSIGNED_SHORT:
188 ctx->Array.Color.StrideB = size*sizeof(GLushort);
189 break;
190 case GL_INT:
191 ctx->Array.Color.StrideB = size*sizeof(GLint);
192 break;
193 case GL_UNSIGNED_INT:
194 ctx->Array.Color.StrideB = size*sizeof(GLuint);
195 break;
196 case GL_FLOAT:
197 ctx->Array.Color.StrideB = size*sizeof(GLfloat);
198 break;
199 case GL_DOUBLE:
200 ctx->Array.Color.StrideB = size*sizeof(GLdouble);
201 break;
202 default:
203 gl_error( ctx, GL_INVALID_ENUM, "glColorPointer(type)" );
204 return;
205 }
206 }
207 ctx->Array.Color.Size = size;
208 ctx->Array.Color.Type = type;
209 ctx->Array.Color.Stride = stride;
210 ctx->Array.Color.Ptr = (void *) ptr;
211 ctx->Array.ColorFunc = gl_trans_4ub_tab[size][TYPE_IDX(type)];
212 ctx->Array.ColorEltFunc = gl_trans_elt_4ub_tab[size][TYPE_IDX(type)];
213 ctx->Array.NewArrayState |= VERT_RGBA;
214 ctx->NewState |= _NEW_ARRAY;
215 }
216
217
218
219 void
220 _mesa_FogCoordPointerEXT(GLenum type, GLsizei stride, const GLvoid *ptr)
221 {
222 GET_CURRENT_CONTEXT(ctx);
223
224 if (stride<0) {
225 gl_error( ctx, GL_INVALID_VALUE, "glFogCoordPointer(stride)" );
226 return;
227 }
228
229 ctx->Array.FogCoord.StrideB = stride;
230 if (!stride) {
231 switch (type) {
232 case GL_FLOAT:
233 ctx->Array.FogCoord.StrideB = sizeof(GLfloat);
234 break;
235 case GL_DOUBLE:
236 ctx->Array.FogCoord.StrideB = sizeof(GLdouble);
237 break;
238 default:
239 gl_error( ctx, GL_INVALID_ENUM, "glFogCoordPointer(type)" );
240 return;
241 }
242 }
243 ctx->Array.FogCoord.Type = type;
244 ctx->Array.FogCoord.Stride = stride;
245 ctx->Array.FogCoord.Ptr = (void *) ptr;
246 ctx->Array.FogCoordFunc = gl_trans_1f_tab[TYPE_IDX(type)];
247 ctx->Array.FogCoordEltFunc = gl_trans_elt_1f_tab[TYPE_IDX(type)];
248 ctx->Array.NewArrayState |= VERT_FOG_COORD;
249 ctx->NewState |= _NEW_ARRAY;
250 }
251
252
253 void
254 _mesa_IndexPointer(GLenum type, GLsizei stride, const GLvoid *ptr)
255 {
256 GET_CURRENT_CONTEXT(ctx);
257
258 if (stride<0) {
259 gl_error( ctx, GL_INVALID_VALUE, "glIndexPointer(stride)" );
260 return;
261 }
262
263 ctx->Array.Index.StrideB = stride;
264 if (!stride) {
265 switch (type) {
266 case GL_UNSIGNED_BYTE:
267 ctx->Array.Index.StrideB = sizeof(GLubyte);
268 break;
269 case GL_SHORT:
270 ctx->Array.Index.StrideB = sizeof(GLshort);
271 break;
272 case GL_INT:
273 ctx->Array.Index.StrideB = sizeof(GLint);
274 break;
275 case GL_FLOAT:
276 ctx->Array.Index.StrideB = sizeof(GLfloat);
277 break;
278 case GL_DOUBLE:
279 ctx->Array.Index.StrideB = sizeof(GLdouble);
280 break;
281 default:
282 gl_error( ctx, GL_INVALID_ENUM, "glIndexPointer(type)" );
283 return;
284 }
285 }
286 ctx->Array.Index.Type = type;
287 ctx->Array.Index.Stride = stride;
288 ctx->Array.Index.Ptr = (void *) ptr;
289 ctx->Array.IndexFunc = gl_trans_1ui_tab[TYPE_IDX(type)];
290 ctx->Array.IndexEltFunc = gl_trans_elt_1ui_tab[TYPE_IDX(type)];
291 ctx->Array.NewArrayState |= VERT_INDEX;
292 ctx->NewState |= _NEW_ARRAY;
293 }
294
295
296 void
297 _mesa_SecondaryColorPointerEXT(GLint size, GLenum type,
298 GLsizei stride, const GLvoid *ptr)
299 {
300 GET_CURRENT_CONTEXT(ctx);
301
302 if (size != 3 && size != 4) {
303 gl_error( ctx, GL_INVALID_VALUE, "glColorPointer(size)" );
304 return;
305 }
306 if (stride<0) {
307 gl_error( ctx, GL_INVALID_VALUE, "glColorPointer(stride)" );
308 return;
309 }
310
311 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
312 fprintf(stderr, "glColorPointer( sz %d type %s stride %d )\n", size,
313 gl_lookup_enum_by_nr( type ),
314 stride);
315
316 ctx->Array.SecondaryColor.StrideB = stride;
317 if (!stride) {
318 switch (type) {
319 case GL_BYTE:
320 ctx->Array.SecondaryColor.StrideB = size*sizeof(GLbyte);
321 break;
322 case GL_UNSIGNED_BYTE:
323 ctx->Array.SecondaryColor.StrideB = size*sizeof(GLubyte);
324 break;
325 case GL_SHORT:
326 ctx->Array.SecondaryColor.StrideB = size*sizeof(GLshort);
327 break;
328 case GL_UNSIGNED_SHORT:
329 ctx->Array.SecondaryColor.StrideB = size*sizeof(GLushort);
330 break;
331 case GL_INT:
332 ctx->Array.SecondaryColor.StrideB = size*sizeof(GLint);
333 break;
334 case GL_UNSIGNED_INT:
335 ctx->Array.SecondaryColor.StrideB = size*sizeof(GLuint);
336 break;
337 case GL_FLOAT:
338 ctx->Array.SecondaryColor.StrideB = size*sizeof(GLfloat);
339 break;
340 case GL_DOUBLE:
341 ctx->Array.SecondaryColor.StrideB = size*sizeof(GLdouble);
342 break;
343 default:
344 gl_error( ctx, GL_INVALID_ENUM, "glSecondaryColorPointer(type)" );
345 return;
346 }
347 }
348 ctx->Array.SecondaryColor.Size = 3; /* hardwire */
349 ctx->Array.SecondaryColor.Type = type;
350 ctx->Array.SecondaryColor.Stride = stride;
351 ctx->Array.SecondaryColor.Ptr = (void *) ptr;
352 ctx->Array.SecondaryColorFunc = gl_trans_4ub_tab[size][TYPE_IDX(type)];
353 ctx->Array.SecondaryColorEltFunc = gl_trans_elt_4ub_tab[size][TYPE_IDX(type)];
354 ctx->Array.NewArrayState |= VERT_SPEC_RGB;
355 ctx->NewState |= _NEW_ARRAY;
356 }
357
358
359
360 void
361 _mesa_TexCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
362 {
363 GET_CURRENT_CONTEXT(ctx);
364 GLuint texUnit;
365
366 texUnit = ctx->Array.ActiveTexture;
367
368 if (size<1 || size>4) {
369 gl_error( ctx, GL_INVALID_VALUE, "glTexCoordPointer(size)" );
370 return;
371 }
372 if (stride<0) {
373 gl_error( ctx, GL_INVALID_VALUE, "glTexCoordPointer(stride)" );
374 return;
375 }
376
377 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
378 fprintf(stderr, "glTexCoordPointer( unit %u sz %d type %s stride %d )\n",
379 texUnit,
380 size,
381 gl_lookup_enum_by_nr( type ),
382 stride);
383
384 ctx->Array.TexCoord[texUnit].StrideB = stride;
385 if (!stride) {
386 switch (type) {
387 case GL_SHORT:
388 ctx->Array.TexCoord[texUnit].StrideB = size*sizeof(GLshort);
389 break;
390 case GL_INT:
391 ctx->Array.TexCoord[texUnit].StrideB = size*sizeof(GLint);
392 break;
393 case GL_FLOAT:
394 ctx->Array.TexCoord[texUnit].StrideB = size*sizeof(GLfloat);
395 break;
396 case GL_DOUBLE:
397 ctx->Array.TexCoord[texUnit].StrideB = size*sizeof(GLdouble);
398 break;
399 default:
400 gl_error( ctx, GL_INVALID_ENUM, "glTexCoordPointer(type)" );
401 return;
402 }
403 }
404 ctx->Array.TexCoord[texUnit].Size = size;
405 ctx->Array.TexCoord[texUnit].Type = type;
406 ctx->Array.TexCoord[texUnit].Stride = stride;
407 ctx->Array.TexCoord[texUnit].Ptr = (void *) ptr;
408
409 ctx->Array.TexCoordFunc[texUnit] = gl_trans_4f_tab[size][TYPE_IDX(type)];
410 ctx->Array.TexCoordEltFunc[texUnit] = gl_trans_elt_4f_tab[size][TYPE_IDX(type)];
411 ctx->Array.NewArrayState |= VERT_TEX_ANY(texUnit);
412 ctx->NewState |= _NEW_ARRAY;
413 }
414
415
416
417
418 void
419 _mesa_EdgeFlagPointer(GLsizei stride, const void *vptr)
420 {
421 GET_CURRENT_CONTEXT(ctx);
422 const GLboolean *ptr = (GLboolean *)vptr;
423
424 if (stride<0) {
425 gl_error( ctx, GL_INVALID_VALUE, "glEdgeFlagPointer(stride)" );
426 return;
427 }
428 ctx->Array.EdgeFlag.Stride = stride;
429 ctx->Array.EdgeFlag.StrideB = stride ? stride : sizeof(GLboolean);
430 ctx->Array.EdgeFlag.Ptr = (GLboolean *) ptr;
431 if (stride != sizeof(GLboolean)) {
432 ctx->Array.EdgeFlagFunc = gl_trans_1ub_tab[TYPE_IDX(GL_UNSIGNED_BYTE)];
433 } else {
434 ctx->Array.EdgeFlagFunc = 0;
435 }
436 ctx->Array.EdgeFlagEltFunc = gl_trans_elt_1ub_tab[TYPE_IDX(GL_UNSIGNED_BYTE)];
437 ctx->Array.NewArrayState |= VERT_EDGE;
438 ctx->NewState |= _NEW_ARRAY;
439 }
440
441
442
443
444
445 void
446 _mesa_VertexPointerEXT(GLint size, GLenum type, GLsizei stride,
447 GLsizei count, const GLvoid *ptr)
448 {
449 (void) count;
450 _mesa_VertexPointer(size, type, stride, ptr);
451 }
452
453
454 void
455 _mesa_NormalPointerEXT(GLenum type, GLsizei stride, GLsizei count,
456 const GLvoid *ptr)
457 {
458 (void) count;
459 _mesa_NormalPointer(type, stride, ptr);
460 }
461
462
463 void
464 _mesa_ColorPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count,
465 const GLvoid *ptr)
466 {
467 (void) count;
468 _mesa_ColorPointer(size, type, stride, ptr);
469 }
470
471
472 void
473 _mesa_IndexPointerEXT(GLenum type, GLsizei stride, GLsizei count,
474 const GLvoid *ptr)
475 {
476 (void) count;
477 _mesa_IndexPointer(type, stride, ptr);
478 }
479
480
481 void
482 _mesa_TexCoordPointerEXT(GLint size, GLenum type, GLsizei stride,
483 GLsizei count, const GLvoid *ptr)
484 {
485 (void) count;
486 _mesa_TexCoordPointer(size, type, stride, ptr);
487 }
488
489
490 void
491 _mesa_EdgeFlagPointerEXT(GLsizei stride, GLsizei count, const GLboolean *ptr)
492 {
493 (void) count;
494 _mesa_EdgeFlagPointer(stride, ptr);
495 }
496
497
498
499
500
501 /* KW: Batch function to exec all the array elements in the input
502 * buffer prior to transform. Done only the first time a vertex
503 * buffer is executed or compiled.
504 *
505 * KW: Have to do this after each glEnd if cva isn't active. (also
506 * have to do it after each full buffer)
507 */
508 void gl_exec_array_elements( GLcontext *ctx, struct immediate *IM,
509 GLuint start,
510 GLuint count)
511 {
512 GLuint *flags = IM->Flag;
513 GLuint *elts = IM->Elt;
514 GLuint translate = ctx->Array.Flags;
515 GLuint i;
516
517 if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
518 fprintf(stderr, "exec_array_elements %d .. %d\n", start, count);
519
520 if (translate & VERT_OBJ_ANY)
521 (ctx->Array.VertexEltFunc)( IM->Obj,
522 &ctx->Array.Vertex,
523 flags, elts, (VERT_ELT|VERT_OBJ_ANY),
524 start, count);
525
526 if (translate & VERT_NORM)
527 (ctx->Array.NormalEltFunc)( IM->Normal,
528 &ctx->Array.Normal,
529 flags, elts, (VERT_ELT|VERT_NORM),
530 start, count);
531
532 if (translate & VERT_EDGE)
533 (ctx->Array.EdgeFlagEltFunc)( IM->EdgeFlag,
534 &ctx->Array.EdgeFlag,
535 flags, elts, (VERT_ELT|VERT_EDGE),
536 start, count);
537
538 if (translate & VERT_RGBA)
539 (ctx->Array.ColorEltFunc)( IM->Color,
540 &ctx->Array.Color,
541 flags, elts, (VERT_ELT|VERT_RGBA),
542 start, count);
543
544
545 if (translate & VERT_SPEC_RGB)
546 (ctx->Array.SecondaryColorEltFunc)( IM->SecondaryColor,
547 &ctx->Array.SecondaryColor,
548 flags, elts, (VERT_ELT|VERT_SPEC_RGB),
549 start, count);
550
551 if (translate & VERT_FOG_COORD)
552 (ctx->Array.FogCoordEltFunc)( IM->FogCoord,
553 &ctx->Array.FogCoord,
554 flags, elts, (VERT_ELT|VERT_FOG_COORD),
555 start, count);
556
557 if (translate & VERT_INDEX)
558 (ctx->Array.IndexEltFunc)( IM->Index,
559 &ctx->Array.Index,
560 flags, elts, (VERT_ELT|VERT_INDEX),
561 start, count);
562
563 if (translate & VERT_TEX0_ANY)
564 (ctx->Array.TexCoordEltFunc[0])( IM->TexCoord[0],
565 &ctx->Array.TexCoord[0],
566 flags, elts, (VERT_ELT|VERT_TEX0_ANY),
567 start, count);
568
569 if (translate & VERT_TEX1_ANY)
570 (ctx->Array.TexCoordEltFunc[1])( IM->TexCoord[1],
571 &ctx->Array.TexCoord[1],
572 flags, elts, (VERT_ELT|VERT_TEX1_ANY),
573 start, count);
574
575 #if MAX_TEXTURE_UNITS > 2
576 if (translate & VERT_TEX2_ANY)
577 (ctx->Array.TexCoordEltFunc[2])( IM->TexCoord[2],
578 &ctx->Array.TexCoord[2],
579 flags, elts, (VERT_ELT|VERT_TEX2_ANY),
580 start, count);
581 #endif
582 #if MAX_TEXTURE_UNITS > 3
583 if (translate & VERT_TEX3_ANY)
584 (ctx->Array.TexCoordEltFunc[3])( IM->TexCoord[3],
585 &ctx->Array.TexCoord[3],
586 flags, elts, (VERT_ELT|VERT_TEX3_ANY),
587 start, count);
588 #endif
589
590 for (i = start ; i < count ; i++)
591 if (flags[i] & VERT_ELT)
592 flags[i] |= translate;
593
594 }
595
596
597
598 /* Enough funny business going on in here it might be quicker to use a
599 * function pointer.
600 */
601 #define ARRAY_ELT( IM, i ) \
602 { \
603 GLuint count = IM->Count; \
604 IM->Elt[count] = i; \
605 IM->Flag[count] = ((IM->Flag[count] & IM->ArrayAndFlags) | \
606 VERT_ELT); \
607 IM->FlushElt |= IM->ArrayEltFlush; \
608 IM->Count = count += IM->ArrayIncr; \
609 if (count == VB_MAX) \
610 _mesa_maybe_transform_vb( IM ); \
611 }
612
613
614 void
615 _mesa_ArrayElement( GLint i )
616 {
617 GET_IMMEDIATE;
618 ARRAY_ELT( IM, i );
619 }
620
621
622 static void
623 gl_ArrayElement( GLcontext *CC, GLint i )
624 {
625 struct immediate *im = CC->input;
626 ARRAY_ELT( im, i );
627 }
628
629
630
631 void
632 _mesa_DrawArrays(GLenum mode, GLint start, GLsizei count)
633 {
634 GET_CURRENT_CONTEXT(ctx);
635 struct vertex_buffer *VB = ctx->VB;
636 GLint i;
637
638 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDrawArrays");
639
640 if (count<0) {
641 gl_error( ctx, GL_INVALID_VALUE, "glDrawArrays(count)" );
642 return;
643 }
644
645 if (!ctx->CompileFlag && ctx->Array.Vertex.Enabled) {
646 GLint remaining = count;
647 GLint i;
648 struct gl_client_array *Normal;
649 struct gl_client_array *Color;
650 struct gl_client_array *SecondaryColor;
651 struct gl_client_array *FogCoord;
652 struct gl_client_array *Index;
653 struct gl_client_array *TexCoord[MAX_TEXTURE_UNITS];
654 struct gl_client_array *EdgeFlag;
655 struct immediate *IM = VB->IM;
656 struct gl_pipeline *elt = &ctx->CVA.elt;
657 GLboolean relock;
658 GLuint fallback, required;
659
660 if (ctx->NewState)
661 gl_update_state( ctx );
662
663 /* Just turn off cva on this path. Could be useful for multipass
664 * rendering to keep it turned on.
665 */
666 relock = ctx->CompileCVAFlag;
667
668 if (relock) {
669 ctx->CompileCVAFlag = 0;
670 elt->pipeline_valid = 0;
671 }
672
673 if (!elt->pipeline_valid)
674 gl_build_immediate_pipeline( ctx );
675
676 required = elt->inputs;
677 fallback = (elt->inputs & ~ctx->Array.Summary);
678
679 /* The translate function doesn't do anything about size. It
680 * just ensures that type and stride come out right.
681 */
682 IM->v.Obj.size = ctx->Array.Vertex.Size;
683
684 if (required & VERT_RGBA) {
685 Color = &ctx->Array.Color;
686 if (fallback & VERT_RGBA) {
687 Color = &ctx->Fallback.Color;
688 ctx->Array.ColorFunc =
689 gl_trans_4ub_tab[4][TYPE_IDX(GL_UNSIGNED_BYTE)];
690 }
691 }
692
693 if (required & VERT_SPEC_RGB)
694 {
695 SecondaryColor = &ctx->Array.SecondaryColor;
696 if (fallback & VERT_SPEC_RGB) {
697 SecondaryColor = &ctx->Fallback.SecondaryColor;
698 ctx->Array.SecondaryColorFunc =
699 gl_trans_4ub_tab[4][TYPE_IDX(GL_UNSIGNED_BYTE)];
700 }
701 }
702
703 if (required & VERT_FOG_COORD)
704 {
705 FogCoord = &ctx->Array.FogCoord;
706 if (fallback & VERT_FOG_COORD) {
707 FogCoord = &ctx->Fallback.FogCoord;
708 ctx->Array.FogCoordFunc =
709 gl_trans_1f_tab[TYPE_IDX(GL_FLOAT)];
710 }
711 }
712
713 if (required & VERT_INDEX) {
714 Index = &ctx->Array.Index;
715 if (fallback & VERT_INDEX) {
716 Index = &ctx->Fallback.Index;
717 ctx->Array.IndexFunc = gl_trans_1ui_tab[TYPE_IDX(GL_UNSIGNED_INT)];
718 }
719 }
720
721 for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++) {
722 GLuint flag = VERT_TEX_ANY(i);
723
724 if (required & flag) {
725 TexCoord[i] = &ctx->Array.TexCoord[i];
726
727 if (fallback & flag) {
728 TexCoord[i] = &ctx->Fallback.TexCoord[i];
729 TexCoord[i]->Size = gl_texcoord_size( ctx->Current.Flag, i );
730
731 ctx->Array.TexCoordFunc[i] =
732 gl_trans_4f_tab[TexCoord[i]->Size][TYPE_IDX(GL_FLOAT)];
733 }
734 }
735 }
736
737 if (ctx->Array.Flags != ctx->Array.Flag[0]) {
738 for (i = 0 ; i < VB_MAX ; i++)
739 ctx->Array.Flag[i] = ctx->Array.Flags;
740 }
741
742 if (required & VERT_NORM) {
743 Normal = &ctx->Array.Normal;
744 if (fallback & VERT_NORM) {
745 Normal = &ctx->Fallback.Normal;
746 ctx->Array.NormalFunc = gl_trans_3f_tab[TYPE_IDX(GL_FLOAT)];
747 }
748 }
749
750 if ( required & VERT_EDGE ) {
751 if (mode == GL_TRIANGLES ||
752 mode == GL_QUADS ||
753 mode == GL_POLYGON) {
754 EdgeFlag = &ctx->Array.EdgeFlag;
755 if (fallback & VERT_EDGE) {
756 EdgeFlag = &ctx->Fallback.EdgeFlag;
757 ctx->Array.EdgeFlagFunc =
758 gl_trans_1ub_tab[TYPE_IDX(GL_UNSIGNED_BYTE)];
759 }
760 }
761 else
762 required &= ~VERT_EDGE;
763 }
764
765 VB->Primitive = IM->Primitive;
766 VB->NextPrimitive = IM->NextPrimitive;
767 VB->MaterialMask = IM->MaterialMask;
768 VB->Material = IM->Material;
769 VB->BoundsPtr = 0;
770
771 while (remaining > 0) {
772 GLint vbspace = VB_MAX - VB_START;
773 GLuint count, n;
774
775 if (vbspace >= remaining) {
776 n = remaining;
777 VB->LastPrimitive = VB_START + n;
778 }
779 else {
780 n = vbspace;
781 VB->LastPrimitive = VB_START;
782 }
783
784 VB->CullMode = 0;
785
786 ctx->Array.VertexFunc( IM->Obj + VB_START,
787 &ctx->Array.Vertex, start, n );
788
789 if (required & VERT_NORM) {
790 ctx->Array.NormalFunc( IM->Normal + VB_START,
791 Normal, start, n );
792 }
793
794 if (required & VERT_EDGE) {
795 ctx->Array.EdgeFlagFunc( IM->EdgeFlag + VB_START,
796 EdgeFlag, start, n );
797 }
798
799 if (required & VERT_RGBA) {
800 ctx->Array.ColorFunc( IM->Color + VB_START,
801 Color, start, n );
802 }
803
804 if (required & VERT_SPEC_RGB) {
805 ctx->Array.SecondaryColorFunc( IM->SecondaryColor + VB_START,
806 SecondaryColor, start, n );
807 }
808
809 if (required & VERT_FOG_COORD) {
810 ctx->Array.FogCoordFunc( IM->FogCoord + VB_START,
811 FogCoord, start, n );
812 }
813
814 if (required & VERT_INDEX) {
815 ctx->Array.IndexFunc( IM->Index + VB_START,
816 Index, start, n );
817 }
818
819 if (required & VERT_TEX0_ANY) {
820 IM->v.TexCoord[0].size = TexCoord[0]->Size;
821 ctx->Array.TexCoordFunc[0]( IM->TexCoord[0] + VB_START,
822 TexCoord[0], start, n );
823 }
824
825 if (required & VERT_TEX1_ANY) {
826 IM->v.TexCoord[1].size = TexCoord[1]->Size;
827 ctx->Array.TexCoordFunc[1]( IM->TexCoord[1] + VB_START,
828 TexCoord[1], start, n );
829 }
830 #if MAX_TEXTURE_UNITS > 2
831 if (required & VERT_TEX2_ANY) {
832 IM->v.TexCoord[2].size = TexCoord[2]->Size;
833 ctx->Array.TexCoordFunc[2]( IM->TexCoord[2] + VB_START,
834 TexCoord[2], start, n );
835 }
836 #endif
837 #if MAX_TEXTURE_UNITS > 3
838 if (required & VERT_TEX3_ANY) {
839 IM->v.TexCoord[3].size = TexCoord[3]->Size;
840 ctx->Array.TexCoordFunc[3]( IM->TexCoord[3] + VB_START,
841 TexCoord[3], start, n );
842 }
843 #endif
844
845 VB->ObjPtr = &IM->v.Obj;
846 VB->NormalPtr = &IM->v.Normal;
847 VB->ColorPtr = &IM->v.Color;
848 VB->Color[0] = VB->Color[1] = VB->ColorPtr;
849 VB->IndexPtr = &IM->v.Index;
850 VB->EdgeFlagPtr = &IM->v.EdgeFlag;
851 VB->SecondaryColorPtr = &IM->v.SecondaryColor;
852 VB->FogCoordPtr = &IM->v.FogCoord;
853 for (i = 0; i < MAX_TEXTURE_UNITS; i++) {
854 VB->TexCoordPtr[i] = &IM->v.TexCoord[i];
855 }
856
857 VB->Flag = ctx->Array.Flag;
858 VB->OrFlag = ctx->Array.Flags;
859
860 VB->Start = IM->Start = VB_START;
861 count = VB->Count = IM->Count = VB_START + n;
862
863 #define RESET_VEC(v, t, s, c) (v.start = t v.data[s], v.count = c)
864
865 RESET_VEC(IM->v.Obj, (GLfloat *), VB_START, count);
866 RESET_VEC(IM->v.Normal, (GLfloat *), VB_START, count);
867 for (i = 0; i < MAX_TEXTURE_UNITS; i++) {
868 RESET_VEC(IM->v.TexCoord[i], (GLfloat *), VB_START, count);
869 }
870 RESET_VEC(IM->v.Index, &, VB_START, count);
871 RESET_VEC(IM->v.Elt, &, VB_START, count);
872 RESET_VEC(IM->v.EdgeFlag, &, VB_START, count);
873 RESET_VEC(IM->v.Color, (GLubyte *), VB_START, count);
874 RESET_VEC(VB->Clip, (GLfloat *), VB_START, count);
875 RESET_VEC(VB->Eye, (GLfloat *), VB_START, count);
876 RESET_VEC(VB->Win, (GLfloat *), VB_START, count);
877 RESET_VEC(VB->BColor, (GLubyte *), VB_START, count);
878 RESET_VEC(VB->BIndex, &, VB_START, count);
879
880 VB->NextPrimitive[VB->CopyStart] = VB->Count;
881 VB->Primitive[VB->CopyStart] = mode;
882 ctx->Array.Flag[count] |= VERT_END_VB;
883
884 /* Transform and render.
885 */
886 gl_run_pipeline( VB );
887 gl_reset_vb( VB );
888
889 ctx->Array.Flag[count] = ctx->Array.Flags;
890 ctx->Array.Flag[VB_START] = ctx->Array.Flags;
891
892 start += n;
893 remaining -= n;
894 }
895
896 gl_reset_input( ctx );
897
898 if (relock) {
899 ctx->CompileCVAFlag = relock;
900 elt->pipeline_valid = 0;
901 }
902 }
903 else if (ctx->Array.Vertex.Enabled)
904 {
905 /* The GL_COMPILE and GL_COMPILE_AND_EXECUTE cases. These
906 * could be handled by the above code, but it gets a little
907 * complex. The generated list is still of good quality
908 * this way.
909 */
910 gl_Begin( ctx, mode );
911 for (i=0;i<count;i++) {
912 gl_ArrayElement( ctx, start+i );
913 }
914 gl_End( ctx );
915 }
916 else
917 {
918 /* The degenerate case where vertices are not enabled - only
919 * need to process the very final array element, as all of the
920 * preceding ones would be overwritten anyway.
921 */
922 gl_Begin( ctx, mode );
923 gl_ArrayElement( ctx, start+count );
924 gl_End( ctx );
925 }
926 }
927
928
929
930 /* KW: Exactly fakes the effects of calling glArrayElement multiple times.
931 */
932 #if 1
933 #define DRAW_ELT(FUNC, TYPE) \
934 static void FUNC( GLcontext *ctx, GLenum mode, \
935 TYPE *indices, GLuint count ) \
936 { \
937 GLuint i,j; \
938 \
939 gl_Begin( ctx, mode ); \
940 \
941 for (j = 0 ; j < count ; ) { \
942 struct immediate *IM = ctx->input; \
943 GLuint start = IM->Start; \
944 GLuint nr = MIN2( VB_MAX, count - j + start ); \
945 GLuint sf = IM->Flag[start]; \
946 IM->FlushElt |= IM->ArrayEltFlush; \
947 \
948 for (i = start ; i < nr ; i++) { \
949 IM->Elt[i] = (GLuint) *indices++; \
950 IM->Flag[i] = VERT_ELT; \
951 } \
952 \
953 if (j == 0) IM->Flag[start] |= sf; \
954 \
955 IM->Count = nr; \
956 j += nr - start; \
957 \
958 if (j == count) \
959 gl_End( ctx ); \
960 _mesa_maybe_transform_vb( IM ); \
961 } \
962 }
963 #else
964 #define DRAW_ELT(FUNC, TYPE) \
965 static void FUNC( GLcontext *ctx, GLenum mode, \
966 TYPE *indices, GLuint count ) \
967 { \
968 int i; \
969 glBegin(mode); \
970 for (i = 0 ; i < count ; i++) \
971 glArrayElement( indices[i] ); \
972 glEnd(); \
973 }
974 #endif
975
976
977 DRAW_ELT( draw_elt_ubyte, GLubyte )
978 DRAW_ELT( draw_elt_ushort, GLushort )
979 DRAW_ELT( draw_elt_uint, GLuint )
980
981
982 static GLuint natural_stride[0x10] =
983 {
984 sizeof(GLbyte), /* 0 */
985 sizeof(GLubyte), /* 1 */
986 sizeof(GLshort), /* 2 */
987 sizeof(GLushort), /* 3 */
988 sizeof(GLint), /* 4 */
989 sizeof(GLuint), /* 5 */
990 sizeof(GLfloat), /* 6 */
991 2 * sizeof(GLbyte), /* 7 */
992 3 * sizeof(GLbyte), /* 8 */
993 4 * sizeof(GLbyte), /* 9 */
994 sizeof(GLdouble), /* a */
995 0, /* b */
996 0, /* c */
997 0, /* d */
998 0, /* e */
999 0 /* f */
1000 };
1001
1002
1003 void
1004 _mesa_DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices)
1005 {
1006 GET_CURRENT_CONTEXT(ctx);
1007 struct gl_cva *cva;
1008
1009 cva = &ctx->CVA;
1010 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDrawElements");
1011
1012 if (count <= 0) {
1013 if (count < 0)
1014 gl_error( ctx, GL_INVALID_VALUE, "glDrawElements(count)" );
1015 return;
1016 }
1017
1018 if (mode < 0 || mode > GL_POLYGON) {
1019 gl_error( ctx, GL_INVALID_ENUM, "glDrawArrays(mode)" );
1020 return;
1021 }
1022
1023 if (type != GL_UNSIGNED_INT && type != GL_UNSIGNED_BYTE && type != GL_UNSIGNED_SHORT)
1024 {
1025 gl_error( ctx, GL_INVALID_ENUM, "glDrawElements(type)" );
1026 return;
1027 }
1028
1029 if (ctx->NewState)
1030 gl_update_state(ctx);
1031
1032 if (ctx->CompileCVAFlag)
1033 {
1034 /* Treat VERT_ELT like a special client array.
1035 */
1036 ctx->Array.NewArrayState |= VERT_ELT;
1037 ctx->Array.Summary |= VERT_ELT;
1038 ctx->Array.Flags |= VERT_ELT;
1039
1040 cva->elt_mode = mode;
1041 cva->elt_count = count;
1042 cva->Elt.Type = type;
1043 cva->Elt.Ptr = (void *) indices;
1044 cva->Elt.StrideB = natural_stride[TYPE_IDX(type)];
1045 cva->EltFunc = gl_trans_1ui_tab[TYPE_IDX(type)];
1046
1047 if (!cva->pre.pipeline_valid)
1048 gl_build_precalc_pipeline( ctx );
1049 else if (MESA_VERBOSE & VERBOSE_PIPELINE)
1050 fprintf(stderr, ": dont rebuild\n");
1051
1052 gl_cva_force_precalc( ctx );
1053
1054 /* Did we 'precalculate' the render op?
1055 */
1056 if (ctx->CVA.pre.ops & PIPE_OP_RENDER) {
1057 ctx->Array.NewArrayState |= VERT_ELT;
1058 ctx->Array.Summary &= ~VERT_ELT;
1059 ctx->Array.Flags &= ~VERT_ELT;
1060 return;
1061 }
1062
1063 if ( (MESA_VERBOSE&VERBOSE_VARRAY) )
1064 printf("using immediate\n");
1065 }
1066
1067
1068 /* Otherwise, have to use the immediate path to render.
1069 */
1070 switch (type) {
1071 case GL_UNSIGNED_BYTE:
1072 {
1073 GLubyte *ub_indices = (GLubyte *) indices;
1074 if (ctx->Array.Summary & VERT_OBJ_ANY) {
1075 draw_elt_ubyte( ctx, mode, ub_indices, count );
1076 } else {
1077 gl_ArrayElement( ctx, (GLuint) ub_indices[count-1] );
1078 }
1079 }
1080 break;
1081 case GL_UNSIGNED_SHORT:
1082 {
1083 GLushort *us_indices = (GLushort *) indices;
1084 if (ctx->Array.Summary & VERT_OBJ_ANY) {
1085 draw_elt_ushort( ctx, mode, us_indices, count );
1086 } else {
1087 gl_ArrayElement( ctx, (GLuint) us_indices[count-1] );
1088 }
1089 }
1090 break;
1091 case GL_UNSIGNED_INT:
1092 {
1093 GLuint *ui_indices = (GLuint *) indices;
1094 if (ctx->Array.Summary & VERT_OBJ_ANY) {
1095 draw_elt_uint( ctx, mode, ui_indices, count );
1096 } else {
1097 gl_ArrayElement( ctx, ui_indices[count-1] );
1098 }
1099 }
1100 break;
1101 default:
1102 gl_error( ctx, GL_INVALID_ENUM, "glDrawElements(type)" );
1103 break;
1104 }
1105
1106 if (ctx->CompileCVAFlag) {
1107 ctx->Array.NewArrayState |= VERT_ELT;
1108 ctx->Array.Summary &= ~VERT_ELT;
1109 }
1110 }
1111
1112
1113
1114 void
1115 _mesa_InterleavedArrays(GLenum format, GLsizei stride, const GLvoid *pointer)
1116 {
1117 GET_CURRENT_CONTEXT(ctx);
1118 GLboolean tflag, cflag, nflag; /* enable/disable flags */
1119 GLint tcomps, ccomps, vcomps; /* components per texcoord, color, vertex */
1120
1121 GLenum ctype; /* color type */
1122 GLint coffset, noffset, voffset;/* color, normal, vertex offsets */
1123 GLint defstride; /* default stride */
1124 GLint c, f;
1125 GLint coordUnitSave;
1126
1127 f = sizeof(GLfloat);
1128 c = f * ((4*sizeof(GLubyte) + (f-1)) / f);
1129
1130 if (stride<0) {
1131 gl_error( ctx, GL_INVALID_VALUE, "glInterleavedArrays(stride)" );
1132 return;
1133 }
1134
1135 switch (format) {
1136 case GL_V2F:
1137 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_FALSE;
1138 tcomps = 0; ccomps = 0; vcomps = 2;
1139 voffset = 0;
1140 defstride = 2*f;
1141 break;
1142 case GL_V3F:
1143 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_FALSE;
1144 tcomps = 0; ccomps = 0; vcomps = 3;
1145 voffset = 0;
1146 defstride = 3*f;
1147 break;
1148 case GL_C4UB_V2F:
1149 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
1150 tcomps = 0; ccomps = 4; vcomps = 2;
1151 ctype = GL_UNSIGNED_BYTE;
1152 coffset = 0;
1153 voffset = c;
1154 defstride = c + 2*f;
1155 break;
1156 case GL_C4UB_V3F:
1157 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
1158 tcomps = 0; ccomps = 4; vcomps = 3;
1159 ctype = GL_UNSIGNED_BYTE;
1160 coffset = 0;
1161 voffset = c;
1162 defstride = c + 3*f;
1163 break;
1164 case GL_C3F_V3F:
1165 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
1166 tcomps = 0; ccomps = 3; vcomps = 3;
1167 ctype = GL_FLOAT;
1168 coffset = 0;
1169 voffset = 3*f;
1170 defstride = 6*f;
1171 break;
1172 case GL_N3F_V3F:
1173 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_TRUE;
1174 tcomps = 0; ccomps = 0; vcomps = 3;
1175 noffset = 0;
1176 voffset = 3*f;
1177 defstride = 6*f;
1178 break;
1179 case GL_C4F_N3F_V3F:
1180 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_TRUE;
1181 tcomps = 0; ccomps = 4; vcomps = 3;
1182 ctype = GL_FLOAT;
1183 coffset = 0;
1184 noffset = 4*f;
1185 voffset = 7*f;
1186 defstride = 10*f;
1187 break;
1188 case GL_T2F_V3F:
1189 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_FALSE;
1190 tcomps = 2; ccomps = 0; vcomps = 3;
1191 voffset = 2*f;
1192 defstride = 5*f;
1193 break;
1194 case GL_T4F_V4F:
1195 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_FALSE;
1196 tcomps = 4; ccomps = 0; vcomps = 4;
1197 voffset = 4*f;
1198 defstride = 8*f;
1199 break;
1200 case GL_T2F_C4UB_V3F:
1201 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_FALSE;
1202 tcomps = 2; ccomps = 4; vcomps = 3;
1203 ctype = GL_UNSIGNED_BYTE;
1204 coffset = 2*f;
1205 voffset = c+2*f;
1206 defstride = c+5*f;
1207 break;
1208 case GL_T2F_C3F_V3F:
1209 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_FALSE;
1210 tcomps = 2; ccomps = 3; vcomps = 3;
1211 ctype = GL_FLOAT;
1212 coffset = 2*f;
1213 voffset = 5*f;
1214 defstride = 8*f;
1215 break;
1216 case GL_T2F_N3F_V3F:
1217 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_TRUE;
1218 tcomps = 2; ccomps = 0; vcomps = 3;
1219 noffset = 2*f;
1220 voffset = 5*f;
1221 defstride = 8*f;
1222 break;
1223 case GL_T2F_C4F_N3F_V3F:
1224 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_TRUE;
1225 tcomps = 2; ccomps = 4; vcomps = 3;
1226 ctype = GL_FLOAT;
1227 coffset = 2*f;
1228 noffset = 6*f;
1229 voffset = 9*f;
1230 defstride = 12*f;
1231 break;
1232 case GL_T4F_C4F_N3F_V4F:
1233 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_TRUE;
1234 tcomps = 4; ccomps = 4; vcomps = 4;
1235 ctype = GL_FLOAT;
1236 coffset = 4*f;
1237 noffset = 8*f;
1238 voffset = 11*f;
1239 defstride = 15*f;
1240 break;
1241 default:
1242 gl_error( ctx, GL_INVALID_ENUM, "glInterleavedArrays(format)" );
1243 return;
1244 }
1245
1246 if (stride==0) {
1247 stride = defstride;
1248 }
1249
1250 _mesa_DisableClientState( GL_EDGE_FLAG_ARRAY );
1251 _mesa_DisableClientState( GL_INDEX_ARRAY );
1252
1253 /* Texcoords */
1254 coordUnitSave = ctx->Array.ActiveTexture;
1255 if (tflag) {
1256 GLint i;
1257 GLint factor = ctx->Array.TexCoordInterleaveFactor;
1258 for (i = 0; i < factor; i++) {
1259 _mesa_ClientActiveTextureARB( (GLenum) (GL_TEXTURE0_ARB + i) );
1260 _mesa_EnableClientState( GL_TEXTURE_COORD_ARRAY );
1261 glTexCoordPointer( tcomps, GL_FLOAT, stride,
1262 (GLubyte *) pointer + i * coffset );
1263 }
1264 for (i = factor; i < ctx->Const.MaxTextureUnits; i++) {
1265 _mesa_ClientActiveTextureARB( (GLenum) (GL_TEXTURE0_ARB + i) );
1266 _mesa_DisableClientState( GL_TEXTURE_COORD_ARRAY );
1267 }
1268 }
1269 else {
1270 GLint i;
1271 for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
1272 _mesa_ClientActiveTextureARB( (GLenum) (GL_TEXTURE0_ARB + i) );
1273 _mesa_DisableClientState( GL_TEXTURE_COORD_ARRAY );
1274 }
1275 }
1276 /* Restore texture coordinate unit index */
1277 _mesa_ClientActiveTextureARB( (GLenum) (GL_TEXTURE0_ARB + coordUnitSave) );
1278
1279
1280 /* Color */
1281 if (cflag) {
1282 _mesa_EnableClientState( GL_COLOR_ARRAY );
1283 glColorPointer( ccomps, ctype, stride,
1284 (GLubyte*) pointer + coffset );
1285 }
1286 else {
1287 _mesa_DisableClientState( GL_COLOR_ARRAY );
1288 }
1289
1290
1291 /* Normals */
1292 if (nflag) {
1293 _mesa_EnableClientState( GL_NORMAL_ARRAY );
1294 glNormalPointer( GL_FLOAT, stride,
1295 (GLubyte*) pointer + noffset );
1296 }
1297 else {
1298 _mesa_DisableClientState( GL_NORMAL_ARRAY );
1299 }
1300
1301 _mesa_EnableClientState( GL_VERTEX_ARRAY );
1302 glVertexPointer( vcomps, GL_FLOAT, stride,
1303 (GLubyte *) pointer + voffset );
1304 }
1305
1306
1307
1308 void
1309 _mesa_DrawRangeElements(GLenum mode, GLuint start,
1310 GLuint end, GLsizei count,
1311 GLenum type, const GLvoid *indices)
1312 {
1313 GET_CURRENT_CONTEXT(ctx);
1314
1315 if (end < start) {
1316 gl_error(ctx, GL_INVALID_VALUE, "glDrawRangeElements( end < start )");
1317 return;
1318 }
1319
1320 #if 0
1321 /*
1322 * XXX something in locked arrays is broken! If start = 0,
1323 * end = 1 and count = 2 we'll take the LockArrays path and
1324 * get incorrect results. See Scott McMillan's bug of 3 Jan 2000.
1325 * For now, don't use locked arrays.
1326 */
1327 if (!ctx->Array.LockCount && 2*count > (GLint) 3*(end-start)) {
1328 glLockArraysEXT( start, end );
1329 glDrawElements( mode, count, type, indices );
1330 glUnlockArraysEXT();
1331 } else {
1332 glDrawElements( mode, count, type, indices );
1333 }
1334 #else
1335 glDrawElements( mode, count, type, indices );
1336 #endif
1337 }
1338
1339
1340
1341 void gl_update_client_state( GLcontext *ctx )
1342 {
1343 static const GLuint sz_flags[5] = {
1344 0,
1345 0,
1346 VERT_OBJ_2,
1347 VERT_OBJ_23,
1348 VERT_OBJ_234
1349 };
1350 static const GLuint tc_flags[5] = {
1351 0,
1352 VERT_TEX0_12,
1353 VERT_TEX0_12,
1354 VERT_TEX0_123,
1355 VERT_TEX0_1234
1356 };
1357 GLint i;
1358
1359 ctx->Array.Flags = 0;
1360 ctx->Array.Summary = 0;
1361 ctx->input->ArrayIncr = 0;
1362
1363 if (ctx->Array.Normal.Enabled) ctx->Array.Flags |= VERT_NORM;
1364 if (ctx->Array.Color.Enabled) ctx->Array.Flags |= VERT_RGBA;
1365 if (ctx->Array.SecondaryColor.Enabled) ctx->Array.Flags |= VERT_SPEC_RGB;
1366 if (ctx->Array.FogCoord.Enabled) ctx->Array.Flags |= VERT_FOG_COORD;
1367 if (ctx->Array.Index.Enabled) ctx->Array.Flags |= VERT_INDEX;
1368 if (ctx->Array.EdgeFlag.Enabled) ctx->Array.Flags |= VERT_EDGE;
1369 if (ctx->Array.Vertex.Enabled) {
1370 ctx->Array.Flags |= sz_flags[ctx->Array.Vertex.Size];
1371 ctx->input->ArrayIncr = 1;
1372 }
1373 for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
1374 if (ctx->Array.TexCoord[i].Enabled) {
1375 ctx->Array.Flags |= (tc_flags[ctx->Array.TexCoord[i].Size] << (i * NR_TEXSIZE_BITS));
1376 }
1377 }
1378
1379 /* Not really important any more:
1380 */
1381 ctx->Array.Summary = ctx->Array.Flags & VERT_DATA;
1382 ctx->input->ArrayAndFlags = ~ctx->Array.Flags;
1383 ctx->input->ArrayEltFlush = !(ctx->CompileCVAFlag);
1384 }
1385