Cleanup of derived state calculation prior to seperating software T&L
[mesa.git] / src / mesa / main / varray.c
1 /* $Id: varray.c,v 1.30 2000/11/05 18:40:59 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 /* Restore values:
890 */
891 ctx->Array._Flag[count] = ctx->Array._Flags;
892 ctx->Array._Flag[VB_START] = ctx->Array._Flags;
893
894 start += n;
895 remaining -= n;
896 }
897
898 gl_reset_input( ctx );
899
900 if (relock) {
901 ctx->CompileCVAFlag = relock;
902 elt->pipeline_valid = 0;
903 }
904 }
905 else if (ctx->Array.Vertex.Enabled)
906 {
907 /* The GL_COMPILE and GL_COMPILE_AND_EXECUTE cases. These
908 * could be handled by the above code, but it gets a little
909 * complex. The generated list is still of good quality
910 * this way.
911 */
912 gl_Begin( ctx, mode );
913 for (i=0;i<count;i++) {
914 gl_ArrayElement( ctx, start+i );
915 }
916 gl_End( ctx );
917 }
918 else
919 {
920 /* The degenerate case where vertices are not enabled - only
921 * need to process the very final array element, as all of the
922 * preceding ones would be overwritten anyway.
923 */
924 gl_Begin( ctx, mode );
925 gl_ArrayElement( ctx, start+count );
926 gl_End( ctx );
927 }
928 }
929
930
931
932 /* KW: Exactly fakes the effects of calling glArrayElement multiple times.
933 */
934 #if 1
935 #define DRAW_ELT(FUNC, TYPE) \
936 static void FUNC( GLcontext *ctx, GLenum mode, \
937 TYPE *indices, GLuint count ) \
938 { \
939 GLuint i,j; \
940 \
941 gl_Begin( ctx, mode ); \
942 \
943 for (j = 0 ; j < count ; ) { \
944 struct immediate *IM = ctx->input; \
945 GLuint start = IM->Start; \
946 GLuint nr = MIN2( VB_MAX, count - j + start ); \
947 GLuint sf = IM->Flag[start]; \
948 IM->FlushElt |= IM->ArrayEltFlush; \
949 \
950 for (i = start ; i < nr ; i++) { \
951 IM->Elt[i] = (GLuint) *indices++; \
952 IM->Flag[i] = VERT_ELT; \
953 } \
954 \
955 if (j == 0) IM->Flag[start] |= sf; \
956 \
957 IM->Count = nr; \
958 j += nr - start; \
959 \
960 if (j == count) \
961 gl_End( ctx ); \
962 _mesa_maybe_transform_vb( IM ); \
963 } \
964 }
965 #else
966 #define DRAW_ELT(FUNC, TYPE) \
967 static void FUNC( GLcontext *ctx, GLenum mode, \
968 TYPE *indices, GLuint count ) \
969 { \
970 int i; \
971 glBegin(mode); \
972 for (i = 0 ; i < count ; i++) \
973 glArrayElement( indices[i] ); \
974 glEnd(); \
975 }
976 #endif
977
978
979 DRAW_ELT( draw_elt_ubyte, GLubyte )
980 DRAW_ELT( draw_elt_ushort, GLushort )
981 DRAW_ELT( draw_elt_uint, GLuint )
982
983
984 static GLuint natural_stride[0x10] =
985 {
986 sizeof(GLbyte), /* 0 */
987 sizeof(GLubyte), /* 1 */
988 sizeof(GLshort), /* 2 */
989 sizeof(GLushort), /* 3 */
990 sizeof(GLint), /* 4 */
991 sizeof(GLuint), /* 5 */
992 sizeof(GLfloat), /* 6 */
993 2 * sizeof(GLbyte), /* 7 */
994 3 * sizeof(GLbyte), /* 8 */
995 4 * sizeof(GLbyte), /* 9 */
996 sizeof(GLdouble), /* a */
997 0, /* b */
998 0, /* c */
999 0, /* d */
1000 0, /* e */
1001 0 /* f */
1002 };
1003
1004
1005 void
1006 _mesa_DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices)
1007 {
1008 GET_CURRENT_CONTEXT(ctx);
1009 struct gl_cva *cva;
1010
1011 cva = &ctx->CVA;
1012 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDrawElements");
1013
1014 if (count <= 0) {
1015 if (count < 0)
1016 gl_error( ctx, GL_INVALID_VALUE, "glDrawElements(count)" );
1017 return;
1018 }
1019
1020 if (mode < 0 || mode > GL_POLYGON) {
1021 gl_error( ctx, GL_INVALID_ENUM, "glDrawArrays(mode)" );
1022 return;
1023 }
1024
1025 if (type != GL_UNSIGNED_INT && type != GL_UNSIGNED_BYTE && type != GL_UNSIGNED_SHORT)
1026 {
1027 gl_error( ctx, GL_INVALID_ENUM, "glDrawElements(type)" );
1028 return;
1029 }
1030
1031 if (ctx->NewState)
1032 gl_update_state(ctx);
1033
1034 if (ctx->CompileCVAFlag)
1035 {
1036 /* Treat VERT_ELT like a special client array.
1037 */
1038 ctx->Array._NewArrayState |= VERT_ELT;
1039 ctx->Array._Summary |= VERT_ELT;
1040 ctx->Array._Flags |= VERT_ELT;
1041
1042 cva->elt_mode = mode;
1043 cva->elt_count = count;
1044 cva->Elt.Type = type;
1045 cva->Elt.Ptr = (void *) indices;
1046 cva->Elt.StrideB = natural_stride[TYPE_IDX(type)];
1047 cva->EltFunc = gl_trans_1ui_tab[TYPE_IDX(type)];
1048
1049 if (!cva->pre.pipeline_valid)
1050 gl_build_precalc_pipeline( ctx );
1051 else if (MESA_VERBOSE & VERBOSE_PIPELINE)
1052 fprintf(stderr, ": dont rebuild\n");
1053
1054 gl_cva_force_precalc( ctx );
1055
1056 /* Did we 'precalculate' the render op?
1057 */
1058 if (ctx->CVA.pre.ops & PIPE_OP_RENDER) {
1059 ctx->Array._NewArrayState |= VERT_ELT;
1060 ctx->Array._Summary &= ~VERT_ELT;
1061 ctx->Array._Flags &= ~VERT_ELT;
1062 return;
1063 }
1064
1065 if ( (MESA_VERBOSE&VERBOSE_VARRAY) )
1066 printf("using immediate\n");
1067 }
1068
1069
1070 /* Otherwise, have to use the immediate path to render.
1071 */
1072 switch (type) {
1073 case GL_UNSIGNED_BYTE:
1074 {
1075 GLubyte *ub_indices = (GLubyte *) indices;
1076 if (ctx->Array._Summary & VERT_OBJ_ANY) {
1077 draw_elt_ubyte( ctx, mode, ub_indices, count );
1078 } else {
1079 gl_ArrayElement( ctx, (GLuint) ub_indices[count-1] );
1080 }
1081 }
1082 break;
1083 case GL_UNSIGNED_SHORT:
1084 {
1085 GLushort *us_indices = (GLushort *) indices;
1086 if (ctx->Array._Summary & VERT_OBJ_ANY) {
1087 draw_elt_ushort( ctx, mode, us_indices, count );
1088 } else {
1089 gl_ArrayElement( ctx, (GLuint) us_indices[count-1] );
1090 }
1091 }
1092 break;
1093 case GL_UNSIGNED_INT:
1094 {
1095 GLuint *ui_indices = (GLuint *) indices;
1096 if (ctx->Array._Summary & VERT_OBJ_ANY) {
1097 draw_elt_uint( ctx, mode, ui_indices, count );
1098 } else {
1099 gl_ArrayElement( ctx, ui_indices[count-1] );
1100 }
1101 }
1102 break;
1103 default:
1104 gl_error( ctx, GL_INVALID_ENUM, "glDrawElements(type)" );
1105 break;
1106 }
1107
1108 if (ctx->CompileCVAFlag) {
1109 ctx->Array._NewArrayState |= VERT_ELT;
1110 ctx->Array._Summary &= ~VERT_ELT;
1111 }
1112 }
1113
1114
1115
1116 void
1117 _mesa_InterleavedArrays(GLenum format, GLsizei stride, const GLvoid *pointer)
1118 {
1119 GET_CURRENT_CONTEXT(ctx);
1120 GLboolean tflag, cflag, nflag; /* enable/disable flags */
1121 GLint tcomps, ccomps, vcomps; /* components per texcoord, color, vertex */
1122
1123 GLenum ctype; /* color type */
1124 GLint coffset, noffset, voffset;/* color, normal, vertex offsets */
1125 GLint defstride; /* default stride */
1126 GLint c, f;
1127 GLint coordUnitSave;
1128
1129 f = sizeof(GLfloat);
1130 c = f * ((4*sizeof(GLubyte) + (f-1)) / f);
1131
1132 if (stride<0) {
1133 gl_error( ctx, GL_INVALID_VALUE, "glInterleavedArrays(stride)" );
1134 return;
1135 }
1136
1137 switch (format) {
1138 case GL_V2F:
1139 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_FALSE;
1140 tcomps = 0; ccomps = 0; vcomps = 2;
1141 voffset = 0;
1142 defstride = 2*f;
1143 break;
1144 case GL_V3F:
1145 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_FALSE;
1146 tcomps = 0; ccomps = 0; vcomps = 3;
1147 voffset = 0;
1148 defstride = 3*f;
1149 break;
1150 case GL_C4UB_V2F:
1151 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
1152 tcomps = 0; ccomps = 4; vcomps = 2;
1153 ctype = GL_UNSIGNED_BYTE;
1154 coffset = 0;
1155 voffset = c;
1156 defstride = c + 2*f;
1157 break;
1158 case GL_C4UB_V3F:
1159 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
1160 tcomps = 0; ccomps = 4; vcomps = 3;
1161 ctype = GL_UNSIGNED_BYTE;
1162 coffset = 0;
1163 voffset = c;
1164 defstride = c + 3*f;
1165 break;
1166 case GL_C3F_V3F:
1167 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
1168 tcomps = 0; ccomps = 3; vcomps = 3;
1169 ctype = GL_FLOAT;
1170 coffset = 0;
1171 voffset = 3*f;
1172 defstride = 6*f;
1173 break;
1174 case GL_N3F_V3F:
1175 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_TRUE;
1176 tcomps = 0; ccomps = 0; vcomps = 3;
1177 noffset = 0;
1178 voffset = 3*f;
1179 defstride = 6*f;
1180 break;
1181 case GL_C4F_N3F_V3F:
1182 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_TRUE;
1183 tcomps = 0; ccomps = 4; vcomps = 3;
1184 ctype = GL_FLOAT;
1185 coffset = 0;
1186 noffset = 4*f;
1187 voffset = 7*f;
1188 defstride = 10*f;
1189 break;
1190 case GL_T2F_V3F:
1191 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_FALSE;
1192 tcomps = 2; ccomps = 0; vcomps = 3;
1193 voffset = 2*f;
1194 defstride = 5*f;
1195 break;
1196 case GL_T4F_V4F:
1197 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_FALSE;
1198 tcomps = 4; ccomps = 0; vcomps = 4;
1199 voffset = 4*f;
1200 defstride = 8*f;
1201 break;
1202 case GL_T2F_C4UB_V3F:
1203 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_FALSE;
1204 tcomps = 2; ccomps = 4; vcomps = 3;
1205 ctype = GL_UNSIGNED_BYTE;
1206 coffset = 2*f;
1207 voffset = c+2*f;
1208 defstride = c+5*f;
1209 break;
1210 case GL_T2F_C3F_V3F:
1211 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_FALSE;
1212 tcomps = 2; ccomps = 3; vcomps = 3;
1213 ctype = GL_FLOAT;
1214 coffset = 2*f;
1215 voffset = 5*f;
1216 defstride = 8*f;
1217 break;
1218 case GL_T2F_N3F_V3F:
1219 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_TRUE;
1220 tcomps = 2; ccomps = 0; vcomps = 3;
1221 noffset = 2*f;
1222 voffset = 5*f;
1223 defstride = 8*f;
1224 break;
1225 case GL_T2F_C4F_N3F_V3F:
1226 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_TRUE;
1227 tcomps = 2; ccomps = 4; vcomps = 3;
1228 ctype = GL_FLOAT;
1229 coffset = 2*f;
1230 noffset = 6*f;
1231 voffset = 9*f;
1232 defstride = 12*f;
1233 break;
1234 case GL_T4F_C4F_N3F_V4F:
1235 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_TRUE;
1236 tcomps = 4; ccomps = 4; vcomps = 4;
1237 ctype = GL_FLOAT;
1238 coffset = 4*f;
1239 noffset = 8*f;
1240 voffset = 11*f;
1241 defstride = 15*f;
1242 break;
1243 default:
1244 gl_error( ctx, GL_INVALID_ENUM, "glInterleavedArrays(format)" );
1245 return;
1246 }
1247
1248 if (stride==0) {
1249 stride = defstride;
1250 }
1251
1252 _mesa_DisableClientState( GL_EDGE_FLAG_ARRAY );
1253 _mesa_DisableClientState( GL_INDEX_ARRAY );
1254
1255 /* Texcoords */
1256 coordUnitSave = ctx->Array.ActiveTexture;
1257 if (tflag) {
1258 GLint i;
1259 GLint factor = ctx->Array.TexCoordInterleaveFactor;
1260 for (i = 0; i < factor; i++) {
1261 _mesa_ClientActiveTextureARB( (GLenum) (GL_TEXTURE0_ARB + i) );
1262 _mesa_EnableClientState( GL_TEXTURE_COORD_ARRAY );
1263 glTexCoordPointer( tcomps, GL_FLOAT, stride,
1264 (GLubyte *) pointer + i * coffset );
1265 }
1266 for (i = factor; i < ctx->Const.MaxTextureUnits; i++) {
1267 _mesa_ClientActiveTextureARB( (GLenum) (GL_TEXTURE0_ARB + i) );
1268 _mesa_DisableClientState( GL_TEXTURE_COORD_ARRAY );
1269 }
1270 }
1271 else {
1272 GLint i;
1273 for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
1274 _mesa_ClientActiveTextureARB( (GLenum) (GL_TEXTURE0_ARB + i) );
1275 _mesa_DisableClientState( GL_TEXTURE_COORD_ARRAY );
1276 }
1277 }
1278 /* Restore texture coordinate unit index */
1279 _mesa_ClientActiveTextureARB( (GLenum) (GL_TEXTURE0_ARB + coordUnitSave) );
1280
1281
1282 /* Color */
1283 if (cflag) {
1284 _mesa_EnableClientState( GL_COLOR_ARRAY );
1285 glColorPointer( ccomps, ctype, stride,
1286 (GLubyte*) pointer + coffset );
1287 }
1288 else {
1289 _mesa_DisableClientState( GL_COLOR_ARRAY );
1290 }
1291
1292
1293 /* Normals */
1294 if (nflag) {
1295 _mesa_EnableClientState( GL_NORMAL_ARRAY );
1296 glNormalPointer( GL_FLOAT, stride,
1297 (GLubyte*) pointer + noffset );
1298 }
1299 else {
1300 _mesa_DisableClientState( GL_NORMAL_ARRAY );
1301 }
1302
1303 _mesa_EnableClientState( GL_VERTEX_ARRAY );
1304 glVertexPointer( vcomps, GL_FLOAT, stride,
1305 (GLubyte *) pointer + voffset );
1306 }
1307
1308
1309
1310 void
1311 _mesa_DrawRangeElements(GLenum mode, GLuint start,
1312 GLuint end, GLsizei count,
1313 GLenum type, const GLvoid *indices)
1314 {
1315 GET_CURRENT_CONTEXT(ctx);
1316
1317 if (end < start) {
1318 gl_error(ctx, GL_INVALID_VALUE, "glDrawRangeElements( end < start )");
1319 return;
1320 }
1321
1322 #if 0
1323 /*
1324 * XXX something in locked arrays is broken! If start = 0,
1325 * end = 1 and count = 2 we'll take the LockArrays path and
1326 * get incorrect results. See Scott McMillan's bug of 3 Jan 2000.
1327 * For now, don't use locked arrays.
1328 */
1329 if (!ctx->Array.LockCount && 2*count > (GLint) 3*(end-start)) {
1330 glLockArraysEXT( start, end );
1331 glDrawElements( mode, count, type, indices );
1332 glUnlockArraysEXT();
1333 } else {
1334 glDrawElements( mode, count, type, indices );
1335 }
1336 #else
1337 glDrawElements( mode, count, type, indices );
1338 #endif
1339 }
1340
1341
1342
1343 void gl_update_client_state( GLcontext *ctx )
1344 {
1345 static const GLuint sz_flags[5] = {
1346 0,
1347 0,
1348 VERT_OBJ_2,
1349 VERT_OBJ_23,
1350 VERT_OBJ_234
1351 };
1352 static const GLuint tc_flags[5] = {
1353 0,
1354 VERT_TEX0_12,
1355 VERT_TEX0_12,
1356 VERT_TEX0_123,
1357 VERT_TEX0_1234
1358 };
1359 GLint i;
1360
1361 ctx->Array._Flags = 0;
1362 ctx->Array._Summary = 0;
1363 ctx->input->ArrayIncr = 0;
1364
1365 if (ctx->Array.Normal.Enabled) ctx->Array._Flags |= VERT_NORM;
1366 if (ctx->Array.Color.Enabled) ctx->Array._Flags |= VERT_RGBA;
1367 if (ctx->Array.SecondaryColor.Enabled) ctx->Array._Flags |= VERT_SPEC_RGB;
1368 if (ctx->Array.FogCoord.Enabled) ctx->Array._Flags |= VERT_FOG_COORD;
1369 if (ctx->Array.Index.Enabled) ctx->Array._Flags |= VERT_INDEX;
1370 if (ctx->Array.EdgeFlag.Enabled) ctx->Array._Flags |= VERT_EDGE;
1371 if (ctx->Array.Vertex.Enabled) {
1372 ctx->Array._Flags |= sz_flags[ctx->Array.Vertex.Size];
1373 ctx->input->ArrayIncr = 1;
1374 }
1375 for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
1376 if (ctx->Array.TexCoord[i].Enabled) {
1377 ctx->Array._Flags |= (tc_flags[ctx->Array.TexCoord[i].Size] << (i * NR_TEXSIZE_BITS));
1378 }
1379 }
1380
1381 /* Not really important any more:
1382 */
1383 ctx->Array._Summary = ctx->Array._Flags & VERT_DATA;
1384 ctx->input->ArrayAndFlags = ~ctx->Array._Flags;
1385 ctx->input->ArrayEltFlush = !(ctx->CompileCVAFlag);
1386 }
1387