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